Merge: src/model/model_index: model index uses BKTree
authorJean Privat <jean@pryen.org>
Mon, 13 Aug 2018 19:25:30 +0000 (15:25 -0400)
committerJean Privat <jean@pryen.org>
Mon, 13 Aug 2018 19:25:30 +0000 (15:25 -0400)
This PR makes ModelIndex use a BKTree (#2718) to speed up Nitweb name similarity search queries on large code corpora.

Levenstein names comparison with 300k+ entities took a bit long (up to 10s for Nitweb with `contrib` and `src` for some queries). The use of BKTree speeds things up and brings those queries under 0.1s.

Pull-Request: #2724
Reviewed-by: Jean Privat <jean@pryen.org>

428 files changed:
.gitignore
Makefile
benchmarks/markdown/bench_markdown.sh
benchmarks/markdown/engines/Makefile
benchmarks/markdown/engines/nitmd2/Makefile [new file with mode: 0644]
benchmarks/markdown/engines/nitmd2/nitmd2.nit [moved from src/doc/doc_phases/doc_phases.nit with 66% similarity]
clib/gc_chooser.h
clib/traces.c
clib/traces.h
contrib/benitlux/src/server/benitlux_controller.nit
contrib/brainfuck/brainfuck.nit
contrib/nitiwiki/src/wiki_edit.nit
contrib/nitrpg/src/web.nit
contrib/opportunity/src/opportunity_controller.nit
contrib/pep8analysis/src/parser/xss/lexer.xss
examples/leapfrog/leapfrog_curses.nit
examples/rosettacode/vignere_cipher.nit
lib/actors/examples/mandelbrot/mandelbrot.nit
lib/base64/base64.nit
lib/binary/binary.nit
lib/core/bytes.nit
lib/core/codecs/iso8859_1.nit
lib/core/codecs/utf8.nit
lib/core/collection/abstract_collection.nit
lib/core/collection/union_find.nit
lib/core/core.nit
lib/core/file.nit
lib/core/fixed_ints.nit
lib/core/kernel.nit
lib/core/stream.nit
lib/core/text/abstract_text.nit
lib/core/text/fixed_ints_text.nit
lib/core/text/flat.nit
lib/core/text/native.nit
lib/core/text/ropes.nit
lib/crapto/xor.nit
lib/crypto/basic_ciphers.nit
lib/crypto/bytes.nit [new file with mode: 0644]
lib/crypto/crypto.nit
lib/crypto/xor_ciphers.nit
lib/gamnit/textures.nit
lib/github/README.md
lib/html/bootstrap.nit
lib/json/static.nit
lib/libevent/libevent.nit
lib/libevent/libevent_example.nit [new file with mode: 0644]
lib/libevent/libevent_test.nit [new file with mode: 0644]
lib/libevent/package.ini
lib/markdown2/markdown2.nit [new file with mode: 0644]
lib/markdown2/markdown_ast.nit [new file with mode: 0644]
lib/markdown2/markdown_block_parsing.nit [new file with mode: 0644]
lib/markdown2/markdown_github.nit [new file with mode: 0644]
lib/markdown2/markdown_html_rendering.nit [new file with mode: 0644]
lib/markdown2/markdown_inline_parsing.nit [new file with mode: 0644]
lib/markdown2/markdown_latex_rendering.nit [new file with mode: 0644]
lib/markdown2/markdown_man_rendering.nit [new file with mode: 0644]
lib/markdown2/markdown_md_rendering.nit [new file with mode: 0644]
lib/markdown2/markdown_rendering.nit [new file with mode: 0644]
lib/markdown2/markdown_wikilinks.nit [new file with mode: 0644]
lib/markdown2/nitmd.nit [new file with mode: 0644]
lib/markdown2/package.ini [new file with mode: 0644]
lib/markdown2/tests/commonmark_gen.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_atx_headings.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_autolinks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_backslash_escapes.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_blank_lines.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_block_quotes.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_code_spans.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_emphasis_and_strong_emphasis.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_entity_and_numeric_character_references.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_fenced_code_blocks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_hard_line_breaks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_html_blocks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_images.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_indented_code_blocks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_inlines.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_link_reference_definitions.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_links.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_list_items.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_lists.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_paragraphs.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_precedence.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_raw_html.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_setext_headings.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_soft_line_breaks.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_tabs.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_textual_content.nit [new file with mode: 0644]
lib/markdown2/tests/test_commonmark_thematic_breaks.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_blocks.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_daring.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_github.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_headings_id.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_inlines.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_issues.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_latex.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_location.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_man.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_md.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_wikilinks.nit [new file with mode: 0644]
lib/msgpack/ext.nit
lib/msgpack/msgpack.nit
lib/msgpack/read.nit
lib/msgpack/serialization_common.nit
lib/msgpack/serialization_write.nit
lib/msgpack/write.nit
lib/nitcorn/file_server.nit
lib/nitcorn/http_response.nit
lib/nitcorn/reactor.nit
lib/nitcorn/token.nit
lib/perfect_hashing/perfect_hashing.nit
lib/popcorn/pop_handlers.nit
lib/posix/README.md [new file with mode: 0644]
lib/posix/ext.nit [moved from lib/posix_ext/posix_ext.nit with 91% similarity]
lib/posix/package.ini [moved from lib/posix_ext/package.ini with 55% similarity]
lib/posix/posix.nit [moved from lib/core/posix.nit with 94% similarity]
lib/privileges/privileges.nit
lib/sha1/sha1.nit
lib/socket/socket_c.nit
lib/trees/bintree.nit
lib/trees/bktree.nit [new file with mode: 0644]
lib/vsm/vsm.nit
lib/websocket/websocket.nit
misc/Nit_Compiler.lttng [new file with mode: 0644]
share/man/nitc.md
share/man/nitpackage.md
share/nitdoc/css/Nitdoc.GitHub.css [deleted file]
share/nitdoc/css/Nitdoc.ModalBox.css [deleted file]
share/nitdoc/css/Nitdoc.QuickSearch.css [deleted file]
share/nitdoc/css/Nitdoc.UI.css [deleted file]
share/nitdoc/css/nitdoc.bootstrap.css
share/nitdoc/css/nitdoc.cards.css [new file with mode: 0644]
share/nitdoc/css/nitdoc.code.css [new file with mode: 0644]
share/nitdoc/css/nitdoc.css
share/nitdoc/css/nitdoc.quicksearch.css [new file with mode: 0644]
share/nitdoc/js/lib/github-api.js [deleted file]
share/nitdoc/js/lib/highlight.js [deleted file]
share/nitdoc/js/lib/nit.js [deleted file]
share/nitdoc/js/lib/utils.js [deleted file]
share/nitdoc/js/nitdoc.quicksearch.js [new file with mode: 0644]
share/nitdoc/js/nitdoc.utils.js [new file with mode: 0644]
share/nitdoc/js/plugins/filtering.js [deleted file]
share/nitdoc/js/plugins/github.js [deleted file]
share/nitdoc/js/plugins/github/commentbox.js [deleted file]
share/nitdoc/js/plugins/github/loginbox.js [deleted file]
share/nitdoc/js/plugins/modalbox.js [deleted file]
share/nitdoc/js/plugins/quicksearch.js [deleted file]
share/nitdoc/resources/icons/github-icon-green.png [deleted file]
share/nitdoc/resources/icons/github-icon-white.png [deleted file]
share/nitdoc/resources/icons/github-icon.png [deleted file]
share/nitweb/directives/entity/card.html
share/nitweb/directives/ui/search-field.html
share/nitweb/views/catalog/person.html
share/nitweb/views/search.html
src/Makefile
src/catalog/catalog.nit
src/catalog/catalog_json.nit [deleted file]
src/compiler/abstract_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit
src/doc/api/api_base.nit
src/doc/api/api_docdown.nit
src/doc/api/api_metrics.nit
src/doc/api/api_model.nit
src/doc/commands/commands_base.nit
src/doc/commands/commands_catalog.nit
src/doc/commands/commands_docdown.nit
src/doc/commands/commands_graph.nit
src/doc/commands/commands_http.nit
src/doc/commands/commands_ini.nit
src/doc/commands/commands_main.nit
src/doc/commands/commands_model.nit
src/doc/commands/commands_parser.nit
src/doc/commands/commands_usage.nit
src/doc/commands/tests/test_commands.nit
src/doc/commands/tests/test_commands_catalog.nit
src/doc/commands/tests/test_commands_graph.nit
src/doc/commands/tests/test_commands_html.sav/test_cmd_search.res [deleted file]
src/doc/commands/tests/test_commands_http.nit
src/doc/commands/tests/test_commands_ini.nit
src/doc/commands/tests/test_commands_json.sav/test_cmd_search.res [deleted file]
src/doc/commands/tests/test_commands_main.nit
src/doc/commands/tests/test_commands_md.sav/test_cmd_search.res [deleted file]
src/doc/commands/tests/test_commands_model.nit
src/doc/commands/tests/test_commands_parser.nit
src/doc/commands/tests/test_commands_usage.nit
src/doc/doc_base.nit [deleted file]
src/doc/doc_commands.nit [deleted file]
src/doc/doc_down.nit [deleted file]
src/doc/doc_phases/doc_concerns.nit [deleted file]
src/doc/doc_phases/doc_graphs.nit [deleted file]
src/doc/doc_phases/doc_hierarchies.nit [deleted file]
src/doc/doc_phases/doc_html.nit [deleted file]
src/doc/doc_phases/doc_indexing.nit [deleted file]
src/doc/doc_phases/doc_intros_redefs.nit [deleted file]
src/doc/doc_phases/doc_lin.nit [deleted file]
src/doc/doc_phases/doc_pages.nit [deleted file]
src/doc/doc_phases/doc_poset.nit [deleted file]
src/doc/doc_phases/doc_readme.nit [deleted file]
src/doc/doc_phases/doc_structure.nit [deleted file]
src/doc/doc_phases/doc_test.nit [deleted file]
src/doc/html_templates/html_components.nit [deleted file]
src/doc/html_templates/html_model.nit [deleted file]
src/doc/html_templates/html_templates.nit [deleted file]
src/doc/html_templates/model_html.nit [deleted file]
src/doc/static/static.nit [moved from src/doc/doc.nit with 85% similarity]
src/doc/static/static_base.nit [new file with mode: 0644]
src/doc/static/static_cards.nit [new file with mode: 0644]
src/doc/static/static_html.nit [new file with mode: 0644]
src/doc/static/static_index.nit [new file with mode: 0644]
src/doc/static/static_structure.nit [new file with mode: 0644]
src/doc/templates/html_commands.nit [moved from src/doc/commands/commands_html.nit with 63% similarity]
src/doc/templates/html_model.nit [moved from src/doc/templates/templates_html.nit with 59% similarity]
src/doc/templates/json_commands.nit [moved from src/doc/commands/commands_json.nit with 91% similarity]
src/doc/templates/json_model.nit [moved from src/doc/templates/templates_json.nit with 82% similarity]
src/doc/templates/md_commands.nit [moved from src/doc/commands/commands_md.nit with 79% similarity]
src/doc/templates/term_model.nit [moved from src/doc/templates/templates_term.nit with 99% similarity]
src/doc/templates/tests/test_html_commands.nit [moved from src/doc/commands/tests/test_commands_html.nit with 64% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ancestors.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ancestors.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_call.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_call.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_children.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_children.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_comment.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_comment.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_descendants.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_descendants.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_entity.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_entity.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_features.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_features.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_clone.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_clone.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_contrib_file.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_contrib_file.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_contrib_file_content.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_contrib_file_content.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_contributors.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_contributors.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_desc.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_desc.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_git.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_git.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_issues.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_issues.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_license.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_license.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_license_file.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_license_file.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_license_file_content.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_license_file_content.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_ini_maintainer.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_ini_maintainer.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_lin.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_lin.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_link.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_link.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_main_compile.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_main_compile.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_mains.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_mains.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_man_options.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_man_options.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_man_synopsis.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_man_synopsis.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_mentities.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_mentities.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_new.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_new.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_param.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_param.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_parents.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_parents.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_return.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_return.res with 100% similarity]
src/doc/templates/tests/test_html_commands.sav/test_cmd_search.res [new file with mode: 0644]
src/doc/templates/tests/test_html_commands.sav/test_cmd_testing.res [moved from src/doc/commands/tests/test_commands_html.sav/test_cmd_testing.res with 100% similarity]
src/doc/templates/tests/test_json_commands.nit [moved from src/doc/commands/tests/test_commands_json.nit with 66% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ancestors.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ancestors.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_call.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_call.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_children.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_children.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_comment.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_comment.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_descendants.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_descendants.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_entity.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_entity.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_features.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_features.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_clone.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_clone.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_contrib_file.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_contrib_file.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_contrib_file_content.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_contrib_file_content.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_contributors.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_contributors.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_desc.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_desc.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_git.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_git.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_issues.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_issues.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_license.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_license.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_license_file.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_license_file.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_license_file_content.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_license_file_content.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_ini_maintainer.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_ini_maintainer.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_lin.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_lin.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_link.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_link.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_main_compile.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_main_compile.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_mains.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_mains.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_man_options.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_man_options.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_man_synopsis.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_man_synopsis.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_mentities.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_mentities.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_new.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_new.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_param.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_param.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_parents.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_parents.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_return.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_return.res with 100% similarity]
src/doc/templates/tests/test_json_commands.sav/test_cmd_search.res [new file with mode: 0644]
src/doc/templates/tests/test_json_commands.sav/test_cmd_testing.res [moved from src/doc/commands/tests/test_commands_json.sav/test_cmd_testing.res with 100% similarity]
src/doc/templates/tests/test_json_model.nit [moved from src/doc/templates/tests/test_templates_json.nit with 98% similarity]
src/doc/templates/tests/test_json_model.sav/test_classdefs_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_classdefs_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_classes_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_classes_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_groups_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_groups_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_modules_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_modules_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_packages_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_packages_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_propdefs_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_propdefs_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_props_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_props_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_json_model.sav/test_refs_to_full_json.res [moved from src/doc/templates/tests/test_templates_json.sav/test_refs_to_full_json.res with 100% similarity]
src/doc/templates/tests/test_md_commands.nit [moved from src/doc/commands/tests/test_commands_md.nit with 63% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ancestors.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ancestors.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_call.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_call.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_children.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_children.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_comment.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_comment.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_descendants.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_descendants.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_entity.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_entity.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_features.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_features.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_clone.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_clone.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_contrib_file.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_contrib_file.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_contrib_file_content.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_contrib_file_content.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_contributors.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_contributors.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_desc.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_desc.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_git.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_git.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_issues.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_issues.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_license.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_license.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_license_file.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_license_file.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_license_file_content.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_license_file_content.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_ini_maintainer.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_ini_maintainer.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_lin.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_lin.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_link.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_link.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_main_compile.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_main_compile.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_mains.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_mains.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_man_options.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_man_options.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_man_synopsis.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_man_synopsis.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_mentities.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_mentities.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_new.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_new.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_param.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_param.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_parents.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_parents.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_return.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_return.res with 100% similarity]
src/doc/templates/tests/test_md_commands.sav/test_cmd_search.res [new file with mode: 0644]
src/doc/templates/tests/test_md_commands.sav/test_cmd_testing.res [moved from src/doc/commands/tests/test_commands_md.sav/test_cmd_testing.res with 100% similarity]
src/doc/term/term.nit
src/doc/term/tests/test_term.nit
src/doc/term/tests/test_term.sav/test_mentity_not_found.res
src/doc/term/tests/test_term.sav/test_search.res
src/doc/term/tests/test_term.sav/test_term_catalog_search.res
src/doc/test_doc_commands.nit [deleted file]
src/doc/vim_autocomplete.nit
src/frontend/parse_examples.nit
src/frontend/tests/test_examples.nit
src/htmlight.nit
src/indexing/code_index.nit [new file with mode: 0644]
src/indexing/tests/test_code_index.nit [new file with mode: 0644]
src/interpreter/naive_interpreter.nit
src/literal.nit
src/metrics/codesmells_metrics.nit
src/metrics/inheritance_metrics.nit
src/metrics/mclassdef_collect.nit
src/metrics/mclasses_metrics.nit
src/metrics/mendel_metrics.nit
src/metrics/method_analyze_metrics.nit
src/metrics/mmodules_metrics.nit
src/metrics/nullables_metrics.nit
src/metrics/rta_metrics.nit
src/model/mdoc.nit
src/model/model_collect.nit
src/model/model_filters.nit
src/model/model_index.nit
src/model/model_views.nit [deleted file]
src/model/mpackage.nit
src/modelize/modelize_property.nit
src/nitcatalog.nit
src/nitdoc.nit
src/nitls.nit
src/nitpackage.nit
src/nituml.nit
src/nitweb.nit
src/nitx.nit
src/semantize/typing.nit
src/test_model_index.nit
src/testing/testing_doc.nit
src/uml/uml_base.nit
src/uml/uml_class.nit
src/uml/uml_module.nit
tests/Darwin.skip
tests/MINGW64_NT.skip
tests/nitdoc.args
tests/niti.skip
tests/nitvm.skip
tests/sav/error_class_glob.res
tests/sav/libevent_test.res [new file with mode: 0644]
tests/sav/nitce/fixme/base_gen_reassign_alt4.res
tests/sav/nitce/fixme/base_gen_reassign_alt5.res
tests/sav/nitce/fixme/base_gen_reassign_alt6.res
tests/sav/nitce/test_new_native.res
tests/sav/nitce/test_new_native_alt1.res
tests/sav/nitdoc_args1.res
tests/sav/nitdoc_args2.res
tests/sav/nitdoc_args3.res
tests/sav/nitdoc_args4.res
tests/sav/nitlight_args1.res
tests/sav/nitlight_args2.res
tests/sav/nitlight_args3.res
tests/sav/nitlight_args5.res
tests/sav/nitmetrics_args1.res
tests/sav/nituml_args3.res
tests/sav/nituml_args4.res
tests/sav/nitunit_args1.res
tests/sav/nitunit_args6.res
tests/sav/simple_file_server.res
tests/sav/test_augmented.res
tests/sav/test_bytes_hexdigit.res
tests/sav/test_catch_multi_threaded.res
tests/sav/test_highlight_args1.res
tests/sav/test_model_index_args10.res
tests/sav/test_model_index_args11.res
tests/sav/test_model_index_args12.res
tests/sav/test_model_index_args13.res
tests/sav/test_model_index_args14.res
tests/sav/test_model_index_args15.res
tests/sav/test_model_index_args16.res
tests/sav/test_model_index_args17.res
tests/sav/test_model_index_args18.res
tests/sav/test_model_index_args19.res
tests/sav/test_model_index_args20.res
tests/sav/test_model_index_args21.res
tests/sav/test_model_index_args8.res
tests/sav/test_model_index_args9.res
tests/sav/test_new_native.res
tests/sav/test_new_native_alt1.res
tests/sav/test_nitcorn.res
tests/sav/test_prefixed_chars.res
tests/sav/test_prefixed_chars_alt1.res [deleted file]
tests/sav/test_rope_bytes.res
tests/sav/test_string_bytes.res
tests/shootout_mandelbrot.nit
tests/shootout_nsieve_bytes_alt.nit
tests/test_augmented.nit
tests/test_binary.nit
tests/test_buffer_unicode.nit
tests/test_catch_multi_threaded.nit
tests/test_model_index.args
tests/test_new_native.nit
tests/test_nitcorn.nit
tests/test_nitunit.nit
tests/test_prefixed_chars.nit
tests/testall.sh

index c4cb96e..1463ddf 100644 (file)
@@ -31,10 +31,12 @@ src/*.dat
 src/*.gnu
 src/*.bin
 src/nitc_0
+src/nitc_0.exe
 
 c_src/*.o
 c_src/*.cksum
 c_src/nitc
+c_src/nitc.exe
 
 csrc2/
 
index 5029f2a..3557372 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -60,10 +60,6 @@ doc/stdlib/index.html: bin/nitdoc bin/nitls
                --custom-brand "<a href=\"http://nitlanguage.org/\">Nitlanguage.org</a>" \
                --custom-overview-text "<p>Documentation for the standard library of Nit<br/>Version $$(git describe)<br/>Date: $$(git show --format="%cd" | head -1)</p>" \
                --custom-footer-text "Nit standard library. Version $$(git describe)." \
-               --github-upstream "nitlang:nit:master" \
-               --github-base-sha1 "$$(git rev-parse HEAD)" \
-               --github-gitdir "." \
-               --source "https://github.com/nitlang/nit/blob/$$(git rev-parse HEAD)/%f#L%l-%L" \
                --piwik-tracker "pratchett.info.uqam.ca/piwik/" \
                --piwik-site-id "2" \
 
@@ -74,10 +70,6 @@ doc/nitc/index.html: bin/nitdoc bin/nitls
                --custom-brand "<a href=\"http://nitlanguage.org/\">Nitlanguage.org</a>" \
                --custom-overview-text "<p>Documentation for the Nit tools<br/>Version $$(git describe)<br/>Date: $$(git show --format="%cd" | head -1)</p>" \
                --custom-footer-text "Nit tools. Version $$(git describe)." \
-               --github-upstream "nitlang:nit:master" \
-               --github-base-sha1 "$$(git rev-parse HEAD)" \
-               --github-gitdir "." \
-               --source "https://github.com/nitlang/nit/blob/$$(git rev-parse HEAD)/%f#L%l-%L" \
                --piwik-tracker "pratchett.info.uqam.ca/piwik/" \
                --piwik-site-id "3"
 
index d6826e1..338ba14 100755 (executable)
@@ -97,6 +97,30 @@ function bench_nitmd-o()
 }
 bench_nitmd-o
 
+function bench_nitmd2()
+{
+       name="$FUNCNAME"
+       skip_test "$name" && return
+       prepare_res $outdir/nitmd2.dat "nitmd2" "nitmd2"
+       for file in $bncdir/*.md; do
+               bench=`basename $file .md`
+               bench_command "$bench" "" "$engdir/nitmd2/nitmd2" "$file" "$s"
+       done
+}
+bench_nitmd2
+
+function bench_nitmd2-o()
+{
+       name="$FUNCNAME"
+       skip_test "$name" && return
+       prepare_res $outdir/nitmd2-o.dat "nitmd2-o" "nitmd2-o"
+       for file in $bncdir/*.md; do
+               bench=`basename $file .md`
+               bench_command "$bench" "" "$engdir/nitmd2/nitmd2-o" "$file" "$s"
+       done
+}
+bench_nitmd2-o
+
 function bench_txtmark()
 {
        name="$FUNCNAME"
index 1eeda88..711d69f 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-all: nitmd/nitmd txtmark/Txtmark.class markdown4j/Markdown4j.class
+all: nitmd/nitmd nitmd2/nitmd2 txtmark/Txtmark.class markdown4j/Markdown4j.class
 
 nitmd/nitmd:
        make -C nitmd
 
+nitmd2/nitmd2:
+       make -C nitmd2
+
 txtmark/Txtmark.class:
        make -C txtmark
 
@@ -30,6 +33,7 @@ pandoc/pandoc:
 
 clean:
        make -C nitmd clean
+       make -C nitmd2 clean
        make -C txtmark clean
        make -C markdown4j clean
        make -C pandoc clean
diff --git a/benchmarks/markdown/engines/nitmd2/Makefile b/benchmarks/markdown/engines/nitmd2/Makefile
new file mode 100644 (file)
index 0000000..526ca83
--- /dev/null
@@ -0,0 +1,32 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Alexandre Terrasa <alexandre@moz-code.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.
+
+NITC=../../../../bin/nitc
+
+all: nitmd2 nitmd2-o
+
+nitmd2:
+       $(NITC) nitmd2.nit
+
+nitmd2-o:
+       $(NITC) --semi-global nitmd2.nit -o $@
+
+test: all
+       ./nitmd2 ../../benches/hello.md 5
+       ./nitmd2-o ../../benches/hello.md 5
+
+clean:
+       rm -rf nitmd2 nitmd2-o
similarity index 66%
rename from src/doc/doc_phases/doc_phases.nit
rename to benchmarks/markdown/engines/nitmd2/nitmd2.nit
index 24969e4..d705618 100644 (file)
@@ -4,7 +4,7 @@
 # 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
+#     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,
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Phases represent the *steps* of the NitDoc generation process.
-#
-# See `DocPhase`.
-module doc_phases
+import markdown2
+
+var file = args.first
+var n = args[1].to_i
 
-import doc_html
-import doc_indexing
-import doc_test
+var str = file.to_path.read_all
+var parser = new MdParser
+var renderer = new HtmlRenderer
+for i in [1..n] do
+       var doc = parser.parse(str)
+       print renderer.render(doc)
+end
index 255e07a..882d310 100644 (file)
@@ -22,5 +22,6 @@ void initialize_gc_option(void); /* Select the wanted GC using envvar `NIT_GC_OP
 
 void gc_register_finalizer(void*); /* Tag a pointer for finalization */
 void gc_finalize(void*, void*); /* Finalize a pointer, implemented in the generated code. */
+void object_destroy_callback(void*, void*); /* call into an object finalizer to record some traces. */
 
 #endif
index 4b01642..9e3c3ad 100644 (file)
@@ -1,4 +1,8 @@
 #define TRACEPOINT_CREATE_PROBES
 #define TRACEPOINT_DEFINE
 
-#include "traces.h"
+#include "nit.common.h"
+
+void object_destroy_callback(void *obj, void *cd){
+       tracepoint(Nit_Compiler, Object_Destroy, (char*)((val*)(obj))->type->name, (uintptr_t)obj);
+}
index 1b88f68..b34af65 100644 (file)
@@ -8,18 +8,32 @@
 #define _TRACES_H
 
 #include <lttng/tracepoint.h>
+#include <gc.h>
 
 TRACEPOINT_EVENT(
-    Nit_Compiler,
-    Object_Instance,
-    TP_ARGS(
-        char*, object_class_arg,
-        int, object_id_arg
-    ),
-    TP_FIELDS(
-        ctf_string(object_class, object_class_arg)
-        ctf_integer(int, object_id, object_id_arg)
-    )
+       Nit_Compiler,
+       Object_Instance,
+       TP_ARGS(
+               char*, object_class_arg,
+               int, object_id_arg
+       ),
+       TP_FIELDS(
+               ctf_string(object_class, object_class_arg)
+               ctf_integer(int, object_id, object_id_arg)
+       )
+)
+
+TRACEPOINT_EVENT(
+       Nit_Compiler,
+       Object_Destroy,
+       TP_ARGS(
+               char*, object_class_arg,
+               int, object_id_arg
+       ),
+       TP_FIELDS(
+               ctf_string(object_class, object_class_arg)
+               ctf_integer(int, object_id, object_id_arg)
+       )
 )
 
 #endif
index a2ab392..8f96182 100644 (file)
@@ -77,7 +77,7 @@ class BenitluxSubscriptionAction
                end
 
                var response = new HttpResponse(200)
-               response.body = template.write_to_string
+               response.body = template
                return response
        end
 end
index 4216952..d207496 100644 (file)
@@ -18,7 +18,7 @@ module brainfuck
 # Interpreter for Brainfuck source code.
 class BFInterpreter
        # Data cells
-       var dr = new Array[Byte]
+       var dr = new Array[Int]
        # Data pointer
        var dp = 0
        # Instruction pointer
@@ -29,7 +29,7 @@ class BFInterpreter
 
        # Create an interpreter for `program`.
        init do
-               dr.add 0u8
+               dr.add 0
        end
 
        # Create an interpreter for the file located at `path`.
@@ -51,35 +51,35 @@ class BFInterpreter
        # Evaluates the current instruction
        fun eval do
                var instr = program[ip]
-               if instr == '.'.ascii then printn dr[dp].ascii
-               if instr == '['.ascii then
-                       if dr[dp] == 0u8 then
+               if instr == u'.' then printn dr[dp].code_point
+               if instr == u'[' then
+                       if dr[dp] == 0 then
                                ip = find_matching_rbra
                                return
                        end
                end
-               if instr == ']'.ascii then
-                       if dr[dp] != 0u8 then
+               if instr == u']' then
+                       if dr[dp] != 0 then
                                ip = find_matching_lbra
                                return
                        end
                end
-               if instr == '>'.ascii then
+               if instr == u'>' then
                        dp += 1
-                       if dp >= dr.length then dr.add(0u8)
+                       if dp >= dr.length then dr.add(0)
                end
-               if instr == '<'.ascii then
+               if instr == u'<' then
                        dp -= 1
                        if dp < 0 then abort
                end
-               if instr == '+'.ascii then
-                       dr[dp] = dr[dp] + 1u8
+               if instr == u'+' then
+                       dr[dp] = dr[dp] + 1
                end
-               if instr == '-'.ascii then
-                       dr[dp] = dr[dp] - 1u8
+               if instr == u'-' then
+                       dr[dp] = dr[dp] - 1
                end
-               if instr == ','.ascii then
-                       dr[dp] = getc.ascii
+               if instr == u',' then
+                       dr[dp] = getc.code_point
                end
        end
 
@@ -89,14 +89,14 @@ class BFInterpreter
                var lbracnt = 0
                loop
                        if pos > program.length then abort
-                       if program[pos] == ']'.ascii then
+                       if program[pos] == u']' then
                                if lbracnt > 0 then
                                        lbracnt -= 1
                                else
                                        break
                                end
                        end
-                       if program[pos] == '['.ascii then lbracnt += 1
+                       if program[pos] == u'[' then lbracnt += 1
                        pos += 1
                end
                return pos
@@ -108,14 +108,14 @@ class BFInterpreter
                var rbracnt = 0
                loop
                        if pos < 0 then abort
-                       if program[pos] == '['.ascii then
+                       if program[pos] == u'[' then
                                if rbracnt > 0 then
                                        rbracnt -= 1
                                else
                                        break
                                end
                        end
-                       if program[pos] == ']'.ascii then rbracnt += 1
+                       if program[pos] == u']' then rbracnt += 1
                        pos -= 1
                end
                return pos
index 3b1abb7..436760b 100644 (file)
@@ -50,7 +50,7 @@ class WikiEditForm
        fun to_http_response: HttpResponse
        do
                var resp = new HttpResponse(200)
-               resp.body = tpl_page.write_to_string
+               resp.body = tpl_page
                return resp
        end
 end
index f624f48..c563af7 100644 (file)
@@ -50,7 +50,7 @@ class RpgAction
                var page = new NitRpgPage(root_url)
                var error = new ErrorPanel(msg)
                page.flow_panels.add error
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 
@@ -95,7 +95,7 @@ class RpgHome
                page = new NitRpgPage(root_url)
                page.side_panels.add new GamesShortListPanel(root_url, games)
                page.flow_panels.add new MDPanel(readme)
-               response.body = page.write_to_string
+               response.body = page
                return response
        end
 
@@ -126,7 +126,7 @@ class ListGames
                page.breadcrumbs = new Breadcrumbs
                page.breadcrumbs.add_link(root_url / "games", "games")
                page.flow_panels.add new GamesListPanel(root_url, games)
-               response.body = page.write_to_string
+               response.body = page
                return response
        end
 end
@@ -196,7 +196,7 @@ class RepoHome
                page.flow_panels.add new PodiumPanel(game)
                page.flow_panels.add new EventListPanel(game, list_limit, list_from)
                page.flow_panels.add new AchievementsListPanel(game)
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 end
@@ -210,7 +210,7 @@ class ListPlayers
                if is_response_error(rsp) then return rsp
                page.breadcrumbs.add_link(game.url / "players", "players")
                page.flow_panels.add new ListPlayersPanel(game)
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 end
@@ -239,7 +239,7 @@ class PlayerHome
                page.flow_panels.add new PlayerWorkPanel(game, player)
                page.flow_panels.add new AchievementsListPanel(player)
                page.flow_panels.add new EventListPanel(player, list_limit, list_from)
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 end
@@ -253,7 +253,7 @@ class ListAchievements
                if is_response_error(rsp) then return rsp
                page.breadcrumbs.add_link(game.url / "achievements", "achievements")
                page.flow_panels.add new AchievementsListPanel(game)
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 end
@@ -278,7 +278,7 @@ class AchievementHome
                page.breadcrumbs.add_link(achievement.url, achievement.name)
                page.flow_panels.add new AchievementPanel(achievement)
                page.flow_panels.add new EventListPanel(achievement, list_limit, list_from)
-               rsp.body = page.write_to_string
+               rsp.body = page
                return rsp
        end
 end
index 214c843..3266502 100644 (file)
@@ -31,7 +31,7 @@ abstract class OpportunityAction
        # TODO: Add a specific body to the bad request page.
        fun bad_req: HttpResponse do
                var rsp = new HttpResponse(400)
-               rsp.body = (new OpportunityHomePage).write_to_string
+               rsp.body = new OpportunityHomePage
                return rsp
        end
 end
@@ -73,7 +73,7 @@ class OpportunityWelcome
                                meetpage.ans = ansset
                                meetpage.meet = meet
                                meetpage.error = "'Meetup name' is a mandatory fields."
-                               rsp.body = meetpage.write_to_string
+                               rsp.body = meetpage
                                return rsp
 
                        end
@@ -85,7 +85,7 @@ class OpportunityWelcome
                                var meetpage = new MeetupCreationPage
                                meetpage.meet = meet
                                meetpage.error = "You need to input at least one answer."
-                               rsp.body = meetpage.write_to_string
+                               rsp.body = meetpage
                                return rsp
                        end
 
@@ -100,7 +100,7 @@ class OpportunityWelcome
 <p>Failed to create event</p>
 <p>This is a server side error, it has been logged.
    You may still want to contact the maintainers of this website.</p>"""
-                               rsp.body = meetpage.write_to_string
+                               rsp.body = meetpage
                                return rsp
                        end
 
@@ -111,22 +111,22 @@ class OpportunityWelcome
                        end
                        db.close
                        var rsp = new HttpResponse(200)
-                       rsp.body = (new MeetupConfirmation(meet)).write_to_string
+                       rsp.body = new MeetupConfirmation(meet)
                        return rsp
                end
                if rq.has("new_meetup") then
                        var rsp = new HttpResponse(200)
                        var page = new MeetupCreationPage
-                       rsp.body = page.write_to_string
+                       rsp.body = page
                        return rsp
                end
                if get.has_key("meetup_id") then
                        var rsp = new HttpResponse(200)
-                       rsp.body = (new OpportunityMeetupPage.from_id(get["meetup_id"])).write_to_string
+                       rsp.body = new OpportunityMeetupPage.from_id(get["meetup_id"])
                        return rsp
                end
                var rsp = new HttpResponse(200)
-               rsp.body = (new OpportunityHomePage).write_to_string
+               rsp.body = new OpportunityHomePage
                return rsp
        end
 
index 6a4d1d0..802755f 100644 (file)
@@ -107,7 +107,7 @@ $ end foreach
                        if sp >= string_len then
                                dfa_state = -1
                        else
-                               var c = string[sp].ascii
+                               var c = string[sp].code_point
                                sp += 1
 
                                var cr = _cr
index da05bf8..995adde 100644 (file)
@@ -124,7 +124,7 @@ redef class PlayScene
                while sys.stdin.poll_in do
                        if sys.stdin.eof then return
                        var c = sys.stdin.read_char
-                       if c == 'q'.ascii then
+                       if c == u'q' then
                                self.exists = false
                                return
                        end
index 565c19e..7fea059 100644 (file)
@@ -19,7 +19,7 @@ fun encrypt(src, key: String): String do
                        continue
                end
 
-               out.add(((c.ascii + key[j].ascii - 2u8 * 'A'.ascii) % 26u8 + 'A'.ascii).ascii)
+               out.add(((c.code_point + key[j].code_point - 2 * u'A') % 26 + u'A').code_point)
                j = (j + 1) % key.length
        end
 
@@ -39,7 +39,7 @@ fun decrypt(src, key: String): String do
                        continue
                end
 
-               out.add(((c.ascii - key[j].ascii + 26u8) % 26u8 + 'A'.ascii).ascii)
+               out.add(((c.code_point - key[j].code_point + 26) % 26 + u'A').code_point)
                j = (j + 1) % key.length
        end
 
index f756970..8fa7be3 100644 (file)
@@ -54,8 +54,8 @@ class Worker
                return res ^-1
        end
 
-       fun put_line(y: Int, line: Array[Byte]) do
-               for i in [0..line.length[ do line[i] = get_byte(i * 8, y).to_b
+       fun put_line(y: Int, line: Array[Int]) do
+               for i in [0..line.length[ do line[i] = get_byte(i * 8, y)
        end
 
        fun work do
@@ -70,7 +70,7 @@ end
 redef class Sys
        var n = 0
        var inv_n: Float is noautoinit
-       var data: Array[Array[Byte]] is noautoinit
+       var data: Array[Array[Int]] is noautoinit
        var crb: Array[Float] is noautoinit
        var cib: Array[Float] is noautoinit
        var atomic = new AtomicInt(0)
@@ -89,8 +89,8 @@ for i in [0..n[ do
        sys.cib[i] = i.to_f * inv_n - 1.0
        sys.crb[i] = i.to_f * inv_n - 1.5
 end
-sys.data = new Array[Array[Byte]].with_capacity(n)
-for i in [0..n[ do sys.data[i] = new Array[Byte].filled_with(0.to_b, (n) / 8)
+sys.data = new Array[Array[Int]].with_capacity(n)
+for i in [0..n[ do sys.data[i] = new Array[Int].filled_with(0, (n) / 8)
 
 # Parallel Approach
 var actors = new Array[Worker]
index 26e1207..622bb51 100644 (file)
@@ -21,38 +21,38 @@ redef class Char
        # Is `self` a valid Base64 character ?
        fun is_base64_char: Bool do
                if code_point >= 127 then return false
-               return ascii.is_base64_char
+               return code_point.is_base64_char
        end
 end
 
-redef class Byte
+redef class Int
        # Is `self` a valid Base64 character ?
        fun is_base64_char: Bool do
-               if self == b'+' then return true
-               if self == b'/' then return true
-               if self > b'Z' then
-                       if self < b'a' then return false
-                       if self <= b'z' then return true
+               if self == u'+' then return true
+               if self == u'/' then return true
+               if self > u'Z' then
+                       if self < u'a' then return false
+                       if self <= u'z' then return true
                        return false
                end
-               if self >= b'A' then return true
-               if self <= b'9' and self >= b'0' then return true
+               if self >= u'A' then return true
+               if self <= u'9' and self >= u'0' then return true
                return false
        end
 
        # Returns the `base64` equivalent of `self`
        #
        # REQUIRE `self`.`is_base64_char`
-       fun to_base64_char: Byte do
-               if self == b'+' then return 62u8
-               if self == b'/' then return 63u8
-               if self > b'Z' then
-                       if self < b'a' then abort
-                       if self <= b'z' then return self - 71u8
+       fun to_base64_char: Int do
+               if self == u'+' then return 62
+               if self == u'/' then return 63
+               if self > u'Z' then
+                       if self < u'a' then abort
+                       if self <= u'z' then return self - 71
                        abort
                end
-               if self >= b'A' then return self - 0x41u8
-               if self <= b'9' and self >= b'0' then return self + 4u8
+               if self >= u'A' then return self - 0x41
+               if self <= u'9' and self >= u'0' then return self + 4
                abort
        end
 end
@@ -79,26 +79,26 @@ redef class CString
 
                var in_off = 0
                for s in [0 .. steps[ do
-                       var ind = ((self[in_off] & 0b1111_1100u8) >> 2).to_i
+                       var ind = (self[in_off] & 0b1111_1100) >> 2
                        result.add base64_bytes[ind]
-                       ind = ((self[in_off] & 0b0000_0011u8) << 4).to_i | ((self[in_off + 1] & 0b1111_0000u8) >> 4).to_i
+                       ind = ((self[in_off] & 0b0000_0011) << 4) | ((self[in_off + 1] & 0b1111_0000) >> 4)
                        result.add base64_bytes[ind]
-                       ind = ((self[in_off + 1] & 0b0000_1111u8) << 2).to_i | ((self[in_off + 2] & 0b1100_0000u8) >> 6).to_i
+                       ind = ((self[in_off + 1] & 0b0000_1111) << 2) | ((self[in_off + 2] & 0b1100_0000) >> 6)
                        result.add base64_bytes[ind]
-                       ind = (self[in_off + 2] & 0b0011_1111u8).to_i
+                       ind = (self[in_off + 2] & 0b0011_1111)
                        result.add base64_bytes[ind]
                        in_off += 3
                end
                if bytes_in_last_step == 1 then
-                       result.add base64_bytes[((self[in_off] & 0b1111_1100u8) >> 2).to_i]
-                       result.add base64_bytes[((self[in_off] & 0b0000_0011u8) << 4).to_i]
+                       result.add base64_bytes[(self[in_off] & 0b1111_1100) >> 2]
+                       result.add base64_bytes[(self[in_off] & 0b0000_0011) << 4]
                else if bytes_in_last_step == 2 then
-                       result.add base64_bytes[((self[in_off] & 0b1111_1100u8) >> 2).to_i]
-                       result.add base64_bytes[(((self[in_off] & 0b0000_0011u8) << 4) | ((self[in_off + 1] & 0b1111_0000u8) >> 4)).to_i]
-                       result.add base64_bytes[((self[in_off + 1] & 0b0000_1111u8) << 2).to_i]
+                       result.add base64_bytes[(self[in_off] & 0b1111_1100) >> 2]
+                       result.add base64_bytes[((self[in_off] & 0b0000_0011) << 4) | ((self[in_off + 1] & 0b1111_0000) >> 4)]
+                       result.add base64_bytes[(self[in_off + 1] & 0b0000_1111) << 2]
                end
                var rempad = if bytes_in_last_step > 0 then 3 - bytes_in_last_step else 0
-               for i in [0 .. rempad[ do result.add b'='
+               for i in [0 .. rempad[ do result.add u'='
 
                return result
        end
@@ -116,7 +116,7 @@ redef class CString
                if length == 0 then return new Bytes.empty
 
                # Avoids constant unboxing
-               var pad = b'='
+               var pad = '='
 
                var result = new Bytes.with_capacity((length / 4 + 1) * 3)
 
@@ -130,15 +130,15 @@ redef class CString
                                break
                        end
                        # Ignore whitespaces
-                       if b <= 0x20u8 then continue
+                       if b <= 0x20 then continue
                        if not b.is_base64_char then continue
                        curr <<= 6
                        curr += b.to_base64_char.to_i
                        cnt += 1
                        if cnt == 4 then
-                               result.add(((curr & 0xFF0000) >> 16).to_b)
-                               result.add(((curr & 0xFF00) >> 8).to_b)
-                               result.add((curr & 0xFF).to_b)
+                               result.add ((curr & 0xFF0000) >> 16)
+                               result.add ((curr & 0xFF00) >> 8)
+                               result.add (curr & 0xFF)
                                curr = 0
                                cnt = 0
                        end
@@ -147,16 +147,16 @@ redef class CString
                        var pads = 0
                        for i in [endpos .. length[ do
                                var b = self[i]
-                               if b <= 0x20u8 then continue
+                               if b <= 0x20 then continue
                                pads += 1
                        end
                        if cnt == 2 then
                                curr >>= 4
-                               result.add(curr.to_b)
+                               result.add(curr)
                        else if cnt == 3 then
                                curr >>= 2
-                               result.add(((curr & 0xFF00) >> 8).to_b)
-                               result.add((curr & 0xFF).to_b)
+                               result.add ((curr & 0xFF00) >> 8)
+                               result.add (curr & 0xFF)
                        end
                end
                return result
@@ -177,19 +177,19 @@ redef class CString
                var rlen = 0
                var opos = length
                for i in [0 .. length[ do
-                       if self[i] == b'=' then
+                       if self[i] == u'=' then
                                opos = i
                                break
                        end
                        if self[i].is_whitespace then continue
-                       if not self[i].is_base64_char then return new Error("Invalid Base64 character at position {i}: {self[i].ascii}")
+                       if not self[i].is_base64_char then return new Error("Invalid Base64 character at position {i}: {self[i].code_point}")
                        rlen += 1
                        if rlen > 4 then rlen -= 4
                end
                var pad = 0
                for i in [opos .. length[ do
                        if self[i].is_whitespace then continue
-                       if self[i] != b'=' then return new Error("Invalid padding character {self[i].ascii} at position {i}")
+                       if self[i] != u'=' then return new Error("Invalid padding character {self[i].code_point} at position {i}")
                        pad += 1
                end
                if rlen + pad != 4 then return new Error("Invalid padding length")
index b8f8b5c..8b39d31 100644 (file)
@@ -18,7 +18,7 @@
 # var w = new FileWriter.open("/tmp/data.bin")
 # w.write "hello"
 # w.write_int64 123456789
-# w.write_byte 3u8
+# w.write_byte 3
 # w.write_float 1.25
 # w.write_double 1.234567
 # w.write_bits(true, false, true)
@@ -70,7 +70,7 @@ redef abstract class Writer
        super BinaryStream
 
        # Write a boolean `value` on a byte, using 0 for `false` and 1 for `true`
-       fun write_bool(value: Bool) do write_byte if value then 1u8 else 0u8
+       fun write_bool(value: Bool) do write_byte if value then 1 else 0
 
        # Write up to 8 `Bool` in a byte
        #
@@ -81,9 +81,9 @@ redef abstract class Writer
        do
                assert bits.length <= 8
 
-               var int = 0u8
+               var int = 0
                for b in bits.length.times do
-                       if bits[b] then int |= 1u8 << (7 - b)
+                       if bits[b] then int |= 1 << (7 - b)
                end
 
                write_byte int
@@ -97,7 +97,7 @@ redef abstract class Writer
        fun write_string(text: Text)
        do
                write text
-               write_byte 0x00u8
+               write_byte 0x00
        end
 
        # Write the length as a 64 bits integer, then the content of `text`
@@ -184,7 +184,7 @@ redef abstract class Reader
                        if byte <= 0 then
                                return buf.to_s
                        end
-                       buf.add byte.to_b
+                       buf.add byte
                end
        end
 
@@ -341,7 +341,7 @@ end
 
 redef class Int
        # Utility for `BinaryWriter`
-       private fun int64_byte_at(index: Int, big_endian: Bool): Byte `{
+       private fun int64_byte_at(index: Int, big_endian: Bool): Int `{
                union {
                        unsigned char bytes[8];
                        int64_t val;
@@ -360,7 +360,7 @@ end
 
 redef class Float
        # Utility for `BinaryWriter`
-       private fun float_byte_at(index: Int, big_endian: Bool): Byte `{
+       private fun float_byte_at(index: Int, big_endian: Bool): Int `{
                union {
                        unsigned char bytes[4];
                        float val;
@@ -377,7 +377,7 @@ redef class Float
        `}
 
        # Utility for `BinaryWriter`
-       private fun double_byte_at(index: Int, big_endian: Bool): Byte `{
+       private fun double_byte_at(index: Int, big_endian: Bool): Int `{
                union {
                        unsigned char bytes[8];
                        double val;
index 84276ac..f386c47 100644 (file)
@@ -22,83 +22,83 @@ intrude import text::flat
 # Any kind of entity which can be searched for in a Sequence of Byte
 interface BytePattern
        # Return the first occurence of `self` in `b`, or -1 if not found
-       fun first_index_in(b: SequenceRead[Byte]): Int do return first_index_in_from(b, 0)
+       fun first_index_in(b: SequenceRead[Int]): Int do return first_index_in_from(b, 0)
 
        # Return the first occurence of `self` in `b` starting at `from`, or -1 if not found
-       fun first_index_in_from(b: SequenceRead[Byte], from: Int): Int is abstract
+       fun first_index_in_from(b: SequenceRead[Int], from: Int): Int is abstract
 
        # Return the last occurence of `self` in `b`, or -1 if not found
-       fun last_index_in(b: SequenceRead[Byte]): Int do return last_index_in_from(b, b.length - 1)
+       fun last_index_in(b: SequenceRead[Int]): Int do return last_index_in_from(b, b.length - 1)
 
        # Return the last occurence of `self` in `b`, or -1 if not found
-       fun last_index_in_from(b: SequenceRead[Byte], from: Int): Int is abstract
+       fun last_index_in_from(b: SequenceRead[Int], from: Int): Int is abstract
 
        # Returns the indexes of all the occurences of `self` in `b`
-       fun search_all_in(b: SequenceRead[Byte]): SequenceRead[Int] is abstract
+       fun search_all_in(b: SequenceRead[Int]): SequenceRead[Int] is abstract
 
        # Length of the pattern
        fun pattern_length: Int is abstract
 
        # Appends `self` to `b`
-       fun append_to(b: Sequence[Byte]) is abstract
+       fun append_to(b: Sequence[Int]) is abstract
 
        # Is `self` a prefix for `b` ?
-       fun is_prefix(b: SequenceRead[Byte]): Bool is abstract
+       fun is_prefix(b: SequenceRead[Int]): Bool is abstract
 
        # Is `self` a suffix for `b` ?
-       fun is_suffix(b: SequenceRead[Byte]): Bool is abstract
+       fun is_suffix(b: SequenceRead[Int]): Bool is abstract
 end
 
-redef class Byte
+redef class Int
        super BytePattern
 
        # Write self as a string into `ns` at position `pos`
        private fun add_digest_at(ns: CString, pos: Int) do
-               var tmp = (0xF0u8 & self) >> 4
-               ns[pos] = if tmp >= 0x0Au8 then tmp + 0x37u8 else tmp + 0x30u8
-               tmp = 0x0Fu8 & self
-               ns[pos + 1] = if tmp >= 0x0Au8 then tmp + 0x37u8 else tmp + 0x30u8
+               var tmp = (0xF0 & self) >> 4
+               ns[pos] = if tmp >= 0x0A then tmp + 0x37 else tmp + 0x30
+               tmp = 0x0F & self
+               ns[pos + 1] = if tmp >= 0x0A then tmp + 0x37 else tmp + 0x30
        end
 
        # Is `self` a valid hexadecimal digit (in ASCII)
        #
        # ~~~nit
        # intrude import core::bytes
-       # assert not '/'.ascii.is_valid_hexdigit
-       # assert '0'.ascii.is_valid_hexdigit
-       # assert '9'.ascii.is_valid_hexdigit
-       # assert not ':'.ascii.is_valid_hexdigit
-       # assert not '@'.ascii.is_valid_hexdigit
-       # assert 'A'.ascii.is_valid_hexdigit
-       # assert 'F'.ascii.is_valid_hexdigit
-       # assert not 'G'.ascii.is_valid_hexdigit
-       # assert not '`'.ascii.is_valid_hexdigit
-       # assert 'a'.ascii.is_valid_hexdigit
-       # assert 'f'.ascii.is_valid_hexdigit
-       # assert not 'g'.ascii.is_valid_hexdigit
+       # assert not u'/'.is_valid_hexdigit
+       # assert u'0'.is_valid_hexdigit
+       # assert u'9'.is_valid_hexdigit
+       # assert not u':'.is_valid_hexdigit
+       # assert not u'@'.is_valid_hexdigit
+       # assert u'A'.is_valid_hexdigit
+       # assert u'F'.is_valid_hexdigit
+       # assert not u'G'.is_valid_hexdigit
+       # assert not u'`'.is_valid_hexdigit
+       # assert u'a'.is_valid_hexdigit
+       # assert u'f'.is_valid_hexdigit
+       # assert not u'g'.is_valid_hexdigit
        # ~~~
        private fun is_valid_hexdigit: Bool do
-               return (self >= 0x30u8 and self <= 0x39u8) or
-                      (self >= 0x41u8 and self <= 0x46u8) or
-                      (self >= 0x61u8 and self <= 0x66u8)
+               return (self >= 0x30 and self <= 0x39) or
+                      (self >= 0x41 and self <= 0x46) or
+                      (self >= 0x61 and self <= 0x66)
        end
 
        # `self` as a hexdigit to its byte value
        #
        # ~~~nit
        # intrude import core::bytes
-       # assert 0x39u8.hexdigit_to_byteval == 0x09u8
-       # assert 0x43u8.hexdigit_to_byteval == 0x0Cu8
+       # assert 0x39.hexdigit_to_byteval == 0x09
+       # assert 0x43.hexdigit_to_byteval == 0x0C
        # ~~~
        #
        # REQUIRE: `self.is_valid_hexdigit`
-       private fun hexdigit_to_byteval: Byte do
-               if self >= 0x30u8 and self <= 0x39u8 then
-                       return self - 0x30u8
-               else if self >= 0x41u8 and self <= 0x46u8 then
-                       return self - 0x37u8
-               else if self >= 0x61u8 and self <= 0x66u8 then
-                       return self - 0x57u8
+       private fun hexdigit_to_byteval: Int do
+               if self >= 0x30 and self <= 0x39 then
+                       return self - 0x30
+               else if self >= 0x41 and self <= 0x46 then
+                       return self - 0x37
+               else if self >= 0x61 and self <= 0x66 then
+                       return self - 0x57
                end
                # Happens only if the requirement is not met.
                # i.e. this abort is here to please the compiler
@@ -130,20 +130,113 @@ redef class Byte
 
        redef fun append_to(b) do b.push self
 
-       #     assert 'b'.ascii.is_suffix("baqsdb".to_bytes)
-       #     assert not 'b'.ascii.is_suffix("baqsd".to_bytes)
+       #     assert u'b'.is_suffix("baqsdb".to_bytes)
+       #     assert not u'b'.is_suffix("baqsd".to_bytes)
        redef fun is_suffix(b) do return b.length != 0 and b.last == self
 
-       #     assert 'b'.ascii.is_prefix("baqsdb".to_bytes)
-       #     assert not 'b'.ascii.is_prefix("aqsdb".to_bytes)
+       #     assert u'b'.is_prefix("baqsdb".to_bytes)
+       #     assert not u'b'.is_prefix("aqsdb".to_bytes)
        redef fun is_prefix(b) do return b.length != 0 and b.first == self
+
+       # A signed big-endian representation of `self`
+       #
+       # ~~~
+       # assert     1.to_bytes.hexdigest ==     "01"
+       # assert   255.to_bytes.hexdigest ==     "FF"
+       # assert   256.to_bytes.hexdigest ==   "0100"
+       # assert 65535.to_bytes.hexdigest ==   "FFFF"
+       # assert 65536.to_bytes.hexdigest == "010000"
+       # ~~~
+       #
+       # Negative values are converted to their two's complement.
+       # Be careful as the result can be ambiguous.
+       #
+       # ~~~
+       # assert     (-1).to_bytes.hexdigest ==     "FF"
+       # assert    (-32).to_bytes.hexdigest ==     "E0"
+       # assert   (-512).to_bytes.hexdigest ==   "FE00"
+       # assert (-65794).to_bytes.hexdigest == "FEFEFE"
+       # ~~~
+       #
+       # Optionally, set `n_bytes` to the desired number of bytes in the output.
+       # This setting can disambiguate the result between positive and negative
+       # integers. Be careful with this parameter as the result may overflow.
+       #
+       # ~~~
+       # assert        1.to_bytes(2).hexdigest ==     "0001"
+       # assert    65535.to_bytes(2).hexdigest ==     "FFFF"
+       # assert     (-1).to_bytes(2).hexdigest ==     "FFFF"
+       # assert   (-512).to_bytes(4).hexdigest == "FFFFFE00"
+       # assert 0x123456.to_bytes(2).hexdigest ==     "3456"
+       # ~~~
+       #
+       # For 0, a Bytes object with single nul byte is returned (instead of an empty Bytes object).
+       #
+       # ~~~
+       # assert 0.to_bytes.hexdigest == "00"
+       # ~~~
+       #
+       # For positive integers, `Bytes::to_i` can reverse the operation.
+       #
+       # ~~~
+       # assert 1234.to_bytes.to_i == 1234
+       # ~~~
+       #
+       # Require self >= 0
+       fun to_bytes(n_bytes: nullable Int): Bytes do
+
+               # If 0, force using at least one byte
+               if self == 0 and n_bytes == null then n_bytes = 1
+
+               # Compute the len (log256)
+               var len = 1
+               var max = 256
+               var s = self.abs
+               while s >= max do
+                       len += 1
+                       max *= 256
+               end
+
+               # Two's complement
+               s = self
+               if self < 0 then
+                       var ff = 0
+                       for j in [0..len[ do
+                               ff *= 0x100
+                               ff += 0xFF
+                       end
+
+                       s = ((-self) ^ ff) + 1
+               end
+
+               # Cut long values
+               if n_bytes != null and len > n_bytes then len = n_bytes
+
+               # Allocate the buffer
+               var cap = n_bytes or else len
+               var res = new Bytes.with_capacity(cap)
+
+               var filler = if self < 0 then 0xFF else 0
+               for i in [0..cap[ do res[i] = filler
+
+               # Fill it starting with the end
+               var i = cap
+               var sum = s
+               while i > cap - len do
+                       i -= 1
+                       res[i] = sum % 256
+                       sum /= 256
+               end
+
+               return res
+       end
 end
 
 # A buffer containing Byte-manipulation facilities
 #
 # Uses Copy-On-Write when persisted
 class Bytes
-       super AbstractArray[Byte]
+       super AbstractArray[Int]
        super BytePattern
 
        # A CString being a char*, it can be used as underlying representation here.
@@ -178,8 +271,8 @@ class Bytes
        redef fun is_empty do return length == 0
 
        #     var b = new Bytes.empty
-       #     b.add 101u8
-       #     assert b[0] == 101u8
+       #     b.add 101
+       #     assert b[0] == 101
        redef fun [](i) do
                assert i >= 0
                assert i < length
@@ -202,13 +295,13 @@ class Bytes
        fun trim: Bytes do
                var st = 0
                while st < length do
-                       if self[st] > 0x20u8 then break
+                       if self[st] > 0x20 then break
                        st += 1
                end
                if st >= length then return new Bytes.empty
                var ed = length - 1
                while ed > 0 do
-                       if self[ed] > 0x20u8 then break
+                       if self[ed] > 0x20 then break
                        ed -= 1
                end
                return slice(st, ed - st + 1)
@@ -251,6 +344,21 @@ class Bytes
                return slice(from, length)
        end
 
+       # Reverse the byte array in place
+       #
+       #     var b = "abcd".to_bytes
+       #     b.reverse
+       #     assert b.to_s == "dcba"
+       fun reverse
+       do
+               var l = length
+               for i in [0..l/2[ do
+                       var tmp = self[i]
+                       self[i] = self[l-i-1]
+                       self[l-i-1] = tmp
+               end
+       end
+
        # Returns self as an hexadecimal digest.
        #
        # Also known as plain hexdump or postscript hexdump.
@@ -289,8 +397,8 @@ class Bytes
                var i = 0
                var oi = 0
                while i < length do
-                       ns[oi] = 0x5Cu8 # b'\\'
-                       ns[oi+1] = 0x78u8 # b'x'
+                       ns[oi] = u'\\'
+                       ns[oi+1] = u'x'
                        self[i].add_digest_at(ns, oi+2)
                        i += 1
                        oi += 4
@@ -313,12 +421,12 @@ class Bytes
                var oi = 0
                while i < length do
                        var c = self[i]
-                       var b = 128u8
-                       while b > 0u8 do
-                               if c & b == 0u8 then
-                                       ns[oi] = 0x30u8 # b'0'
+                       var b = 128
+                       while b > 0 do
+                               if c & b == 0 then
+                                       ns[oi] = u'0'
                                else
-                                       ns[oi] = 0x31u8 # b'1'
+                                       ns[oi] = u'1'
                                end
                                oi += 1
                                b = b >> 1
@@ -379,7 +487,7 @@ class Bytes
                end
 
                # Two's complement is `signed`
-               if signed == true and not_empty and first > 0x80u8 then
+               if signed == true and not_empty and first > 0x80 then
                        var ff = 0
                        for j in [0..length[ do
                                ff *= 0x100
@@ -393,7 +501,7 @@ class Bytes
        end
 
        #     var b = new Bytes.with_capacity(1)
-       #     b[0] = 101u8
+       #     b[0] = 101
        #     assert b.to_s == "e"
        redef fun []=(i, v) do
                if persisted then regen
@@ -404,7 +512,7 @@ class Bytes
        end
 
        #     var b = new Bytes.empty
-       #     b.add 101u8
+       #     b.add 101
        #     assert b.to_s == "e"
        redef fun add(c) do
                if persisted then regen
@@ -431,7 +539,7 @@ class Bytes
        end
 
        #     var b = new Bytes.empty
-       #     b.append([104u8, 101u8, 108u8, 108u8, 111u8])
+       #     b.append([104, 101, 108, 108, 111])
        #     assert b.to_s == "hello"
        redef fun append(arr) do
                if arr isa Bytes then
@@ -442,7 +550,7 @@ class Bytes
        end
 
        #     var b = new Bytes.empty
-       #     b.append([0x41u8, 0x41u8, 0x18u8])
+       #     b.append([0x41, 0x41, 0x18])
        #     b.pop
        #     assert b.to_s == "AA"
        redef fun pop do
@@ -541,7 +649,7 @@ class Bytes
 
        # Splits the content on self when encountering `b`
        #
-       #     var a = "String is string".to_bytes.split_with('s'.ascii)
+       #     var a = "String is string".to_bytes.split_with(u's')
        #     assert a.length == 3
        #     assert a[0].hexdigest == "537472696E672069"
        #     assert a[1].hexdigest == "20"
@@ -561,7 +669,7 @@ class Bytes
 
        # Splits `self` in two parts at the first occurence of `b`
        #
-       #     var a = "String is string".to_bytes.split_once_on('s'.ascii)
+       #     var a = "String is string".to_bytes.split_once_on(u's')
        #     assert a[0].hexdigest == "537472696E672069"
        #     assert a[1].hexdigest == "20737472696E67"
        fun split_once_on(b: BytePattern): Array[Bytes] do
@@ -575,7 +683,7 @@ class Bytes
 
        # Replaces all the occurences of `this` in `self` by `by`
        #
-       #     var b = "String is string".to_bytes.replace(0x20u8, 0x41u8)
+       #     var b = "String is string".to_bytes.replace(0x20, 0x41)
        #     assert b.hexdigest == "537472696E6741697341737472696E67"
        fun replace(pattern: BytePattern, bytes: BytePattern): Bytes do
                if is_empty then return new Bytes.empty
@@ -609,20 +717,20 @@ class Bytes
                var pos = 0
                while pos < length do
                        var b = self[pos]
-                       if b != '%'.ascii then
+                       if b != u'%' then
                                tmp.add b
                                pos += 1
                                continue
                        end
                        if length - pos < 2 then
-                               tmp.add '%'.ascii
+                               tmp.add u'%'
                                pos += 1
                                continue
                        end
                        var bn = self[pos + 1]
                        var bnn = self[pos + 2]
                        if not bn.is_valid_hexdigit or not bnn.is_valid_hexdigit then
-                               tmp.add '%'.ascii
+                               tmp.add u'%'
                                pos += 1
                                continue
                        end
@@ -658,7 +766,7 @@ class Bytes
 end
 
 private class BytesIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        var tgt: CString
 
@@ -675,107 +783,12 @@ private class BytesIterator
        redef fun item do return tgt[index]
 end
 
-redef class Int
-       # A signed big-endian representation of `self`
-       #
-       # ~~~
-       # assert     1.to_bytes.hexdigest ==     "01"
-       # assert   255.to_bytes.hexdigest ==     "FF"
-       # assert   256.to_bytes.hexdigest ==   "0100"
-       # assert 65535.to_bytes.hexdigest ==   "FFFF"
-       # assert 65536.to_bytes.hexdigest == "010000"
-       # ~~~
-       #
-       # Negative values are converted to their two's complement.
-       # Be careful as the result can be ambiguous.
-       #
-       # ~~~
-       # assert     (-1).to_bytes.hexdigest ==     "FF"
-       # assert    (-32).to_bytes.hexdigest ==     "E0"
-       # assert   (-512).to_bytes.hexdigest ==   "FE00"
-       # assert (-65794).to_bytes.hexdigest == "FEFEFE"
-       # ~~~
-       #
-       # Optionally, set `n_bytes` to the desired number of bytes in the output.
-       # This setting can disambiguate the result between positive and negative
-       # integers. Be careful with this parameter as the result may overflow.
-       #
-       # ~~~
-       # assert        1.to_bytes(2).hexdigest ==     "0001"
-       # assert    65535.to_bytes(2).hexdigest ==     "FFFF"
-       # assert     (-1).to_bytes(2).hexdigest ==     "FFFF"
-       # assert   (-512).to_bytes(4).hexdigest == "FFFFFE00"
-       # assert 0x123456.to_bytes(2).hexdigest ==     "3456"
-       # ~~~
-       #
-       # For 0, a Bytes object with single nul byte is returned (instead of an empty Bytes object).
-       #
-       # ~~~
-       # assert 0.to_bytes.hexdigest == "00"
-       # ~~~
-       #
-       # For positive integers, `Bytes::to_i` can reverse the operation.
-       #
-       # ~~~
-       # assert 1234.to_bytes.to_i == 1234
-       # ~~~
-       #
-       # Require self >= 0
-       fun to_bytes(n_bytes: nullable Int): Bytes do
-
-               # If 0, force using at least one byte
-               if self == 0 and n_bytes == null then n_bytes = 1
-
-               # Compute the len (log256)
-               var len = 1
-               var max = 256
-               var s = self.abs
-               while s >= max do
-                       len += 1
-                       max *= 256
-               end
-
-               # Two's complement
-               s = self
-               if self < 0 then
-                       var ff = 0
-                       for j in [0..len[ do
-                               ff *= 0x100
-                               ff += 0xFF
-                       end
-
-                       s = ((-self) ^ ff) + 1
-               end
-
-               # Cut long values
-               if n_bytes != null and len > n_bytes then len = n_bytes
-
-               # Allocate the buffer
-               var cap = n_bytes or else len
-               var res = new Bytes.with_capacity(cap)
-
-               var filler = if self < 0 then 0xFFu8 else 0u8
-               for i in [0..cap[ do res[i] = filler
-
-               # Fill it starting with the end
-               var i = cap
-               var sum = s
-               while i > cap - len do
-                       i -= 1
-                       res[i] = (sum % 256).to_b
-                       sum /= 256
-               end
-
-               return res
-       end
-end
-
 redef class Text
        # Returns a mutable copy of `self`'s bytes
        #
        # ~~~nit
        # assert "String".to_bytes isa Bytes
-       # assert "String".to_bytes == [83u8, 116u8, 114u8, 105u8, 110u8, 103u8]
+       # assert "String".to_bytes == [83, 116, 114, 105, 110, 103]
        # ~~~
        fun to_bytes: Bytes do
                var b = new Bytes.with_capacity(byte_length)
@@ -802,7 +815,7 @@ redef class Text
 
        # Returns a new `Bytes` instance with the digest as content
        #
-       #     assert "0B1F4D".hexdigest_to_bytes == [0x0Bu8, 0x1Fu8, 0x4Du8]
+       #     assert "0B1F4D".hexdigest_to_bytes == [0x0B, 0x1F, 0x4D]
        #     assert "0B1F4D".hexdigest_to_bytes.hexdigest == "0B1F4D"
        #
        # Characters that are not hexadecimal digits are ignored.
@@ -837,7 +850,7 @@ redef class Text
                var ret = new Bytes.with_capacity((dlength+1) / 2)
 
                var i = (dlength+1) % 2 # current hex digit (1=high, 0=low)
-               var byte = 0u8 # current accumulated byte value
+               var byte = 0 # current accumulated byte value
 
                pos = 0
                while pos < max do
@@ -849,7 +862,7 @@ redef class Text
                                        # Last digit known: store and restart
                                        ret.add byte
                                        i = 1
-                                       byte = 0u8
+                                       byte = 0
                                end
                        end
                        pos += 1
@@ -907,7 +920,7 @@ redef class Text
                        else if c == 'x' or c == 'X' then
                                var hx = substring(i + 1, 2)
                                if hx.is_hex then
-                                       res.add(hx.to_hex.to_b)
+                                       res.add hx.to_hex
                                else
                                        res.add_char(c)
                                end
@@ -960,23 +973,23 @@ redef class Text
                while pos < max do
                        var c = b[pos]
                        pos += 1
-                       if c == 0x30u8 or c == 0x31u8 then bitlen += 1 # b'0' or b'1'
+                       if c == u'0' or c == u'1' then bitlen += 1
                end
 
                # Allocate (and take care of the padding)
                var ret = new Bytes.with_capacity((bitlen+7) / 8)
 
                var i = (bitlen+7) % 8 # current bit (7th=128, 0th=1)
-               var byte = 0u8 # current accumulated byte value
+               var byte = 0 # current accumulated byte value
 
                pos = 0
                while pos < max do
                        var c = b[pos]
                        pos += 1
-                       if c == 0x30u8 then # b'0'
+                       if c == u'0' then
                                byte = byte << 1
-                       else if c == 0x31u8 then # b'1'
-                               byte = byte << 1 | 1u8
+                       else if c == u'1' then
+                               byte = byte << 1 | 1
                        else
                                continue
                        end
@@ -986,7 +999,7 @@ redef class Text
                                # Last bit known: store and restart
                                ret.add byte
                                i = 7
-                               byte = 0u8
+                               byte = 0
                        end
                end
                return ret
@@ -1022,7 +1035,7 @@ end
 
 # Joins an array of bytes `arr` separated by `sep`
 #
-#     assert join_bytes(["String".to_bytes, "is".to_bytes, "string".to_bytes], ' '.ascii).hexdigest == "537472696E6720697320737472696E67"
+#     assert join_bytes(["String".to_bytes, "is".to_bytes, "string".to_bytes], u' ').hexdigest == "537472696E6720697320737472696E67"
 fun join_bytes(arr: Array[Bytes], sep: nullable BytePattern): Bytes do
        if arr.is_empty then return new Bytes.empty
        sep = sep or else new Bytes.empty
index 005c569..be52242 100644 (file)
@@ -35,7 +35,7 @@ private class ISO88591Codec
 
        redef fun add_char_to(c, stream) do
                var cp = if c.code_point <= 255 then c else '?'
-               stream[0] = cp.ascii
+               stream[0] = cp.code_point
                return 1
        end
 
@@ -50,9 +50,9 @@ private class ISO88591Codec
                for i in s.chars do
                        var cp = i.code_point
                        if cp <= 255 then
-                               b[pos] = cp.to_b
+                               b[pos] = cp
                        else
-                               b[pos] = 0x3Fu8
+                               b[pos] = 0x3F
                        end
                        pos += 1
                end
index d4d4a38..c37bd35 100644 (file)
@@ -54,7 +54,7 @@ private class UTF8Codec
        redef fun is_valid_char(ns, len) do
                if len == 0 then return 2
                if not ns[0].is_valid_utf8_start then return 2
-               for i in [1 .. len[ do if ns[i] & 0b1100_0000u8 != 0b1000_0000u8 then return 2
+               for i in [1 .. len[ do if ns[i] & 0b1100_0000 != 0b1000_0000 then return 2
                if len != ns[0].u8len then return 1
                return 0
        end
index 04dabfa..b51cd22 100644 (file)
@@ -396,6 +396,7 @@ interface SimpleCollection[E]
        fun add(item: E) is abstract
 
        # Add each item of `coll`.
+       #
        #     var a = [1,2]
        #     a.add_all([3..5])
        #     assert a.has(4)  == true
index 80c5005..864c509 100644 (file)
@@ -140,6 +140,7 @@ class DisjointSet[E]
        end
 
        # Are all elements of `es` in the same subset?
+       #
        #     var s = new DisjointSet[Int]
        #     s.add_all([1,2,3,4,5,6])
        #     s.union_all([1,2,3])
index 54f2550..5261077 100644 (file)
@@ -15,7 +15,6 @@
 # This module is implicitly imported by every module.
 module core
 
-import posix
 import environ
 import time
 import file
index 26f7398..ed4c6c8 100644 (file)
@@ -306,6 +306,9 @@ redef class Int
        private fun fd_to_stream(mode: CString): NativeFile `{
                return fdopen((int)self, mode);
        `}
+
+       # Does the file descriptor `self` refer to a terminal?
+       fun isatty: Bool `{ return isatty(self); `}
 end
 
 # Constant for read-only file streams
@@ -1362,7 +1365,7 @@ redef class FlatString
                var p = last_byte
                var c = its[p]
                var st = _first_byte
-               while p >= st and c != '.'.ascii do
+               while p >= st and c != u'.' do
                        p -= 1
                        c = its[p]
                end
@@ -1379,7 +1382,7 @@ redef class FlatString
                var l = s.last_byte
                var its = s._items
                var min = s._first_byte
-               var sl = '/'.ascii
+               var sl = u'/'
                while l > min and its[l] == sl do l -= 1
                if l == min then return "/"
                var ns = l
@@ -1523,7 +1526,7 @@ private extern class NativeFile `{ FILE* `}
                return (long)res;
        `}
 
-       fun write_byte(value: Byte): Int `{
+       fun write_byte(value: Int): Int `{
                unsigned char b = (unsigned char)value;
                return fwrite(&b, 1, 1, self);
        `}
index ce79f53..521c02b 100644 (file)
@@ -158,9 +158,6 @@ universal Int8
        redef fun to_i32 is intern
        redef fun to_u32 is intern
 
-       # Returns `self` as a Char according to its ASCII value.
-       fun ascii: Char `{ return (uint32_t)self; `}
-
        redef fun distance(i) do return (self - i).to_i
 
        redef fun <=>(other)
@@ -252,9 +249,6 @@ universal Int16
        redef fun *(i) is intern
        redef fun /(i) is intern
 
-       # Returns `self` as a Char according to its ASCII value.
-       fun ascii: Char `{ return (uint32_t)self; `}
-
        # Modulo of `self` with `i`.
        #
        # Returns the remainder of division of `self` by `i`.
@@ -387,9 +381,6 @@ universal UInt16
        redef fun zero do return 0.to_u16
        redef fun value_of(val) do return val.to_u16
 
-       # Returns `self` as a Char according to its ASCII value.
-       fun ascii: Char `{ return (uint32_t)self; `}
-
        # `i` bits shift to the left
        #
        #     assert 5u16 << 1    == 10u16
@@ -500,9 +491,6 @@ universal Int32
        redef fun *(i) is intern
        redef fun /(i) is intern
 
-       # Returns `self` as a Char according to its ASCII value.
-       fun ascii: Char `{ return (uint32_t)self; `}
-
        # Modulo of `self` with `i`.
        #
        # Returns the remainder of division of `self` by `i`.
@@ -624,9 +612,6 @@ universal UInt32
        redef fun *(i) is intern
        redef fun /(i) is intern
 
-       # Returns `self` as a Char according to its ASCII value.
-       fun ascii: Char `{ return (uint32_t)self; `}
-
        # Modulo of `self` with `i`.
        #
        # Returns the remainder of division of `self` by `i`.
index 6a07060..39a5958 100644 (file)
@@ -651,11 +651,6 @@ universal Byte
        #     assert 5u8 >> 1    == 2u8
        fun >>(i: Int): Byte is intern `{ return self >> i; `}
 
-       # Returns the character equivalent of `self`
-       #
-       # REQUIRE: `self <= 127u8`
-       fun ascii: Char is intern `{ return (uint32_t)self; `}
-
        redef fun to_i is intern
        redef fun to_f is intern
        redef fun to_b do return self
@@ -863,8 +858,11 @@ universal Int
 
        # Return the corresponding digit character
        # If 0 <= `self` <= 9, return the corresponding character.
+       #
        #     assert 5.to_c    == '5'
+       #
        # If 10 <= `self` <= 36, return the corresponding letter [a..z].
+       #
        #     assert 15.to_c   == 'f'
        fun to_c: Char
        do
@@ -882,6 +880,9 @@ universal Int
        #     assert 10.abs    == 10
        #     assert 0.abs     == 0
        fun abs: Int do return if self >= 0 then self else -self
+
+       # Is `self` an ASCII whitespace ?
+       fun is_whitespace: Bool do return self == 0x7F or self <= 0x20
 end
 
 # Native characters.
@@ -918,6 +919,24 @@ universal Char
        redef fun successor(i) is intern
        redef fun predecessor(i) is intern
 
+       # The `i`-th char after self (in code point)
+       #
+       # ~~~
+       # assert 'A' + 5 == 'F'
+       # ~~~
+       #
+       # Alias of `successor`.
+       fun +(i: Int): Char do return successor(i)
+
+       # The `i`-th char before self (in code point)
+       #
+       # ~~~
+       # assert 'F' - 5 == 'A'
+       # ~~~
+       #
+       # Alias of `predecessor`.
+       fun -(i: Int): Char do return predecessor(i)
+
        redef fun distance(c)
        do
                var d = self.code_point - c.code_point
@@ -943,14 +962,6 @@ universal Char
                end
        end
 
-       # The ascii value of `self`
-       #
-       #     assert 'a'.ascii    == 97u8
-       #     assert '\n'.ascii   == 10u8
-       #
-       # REQUIRE: `is_ascii`
-       fun ascii: Byte do return code_point.to_b
-
        # The unicode code point value of `self`
        #
        #     assert 'A'.code_point == 65
index 3fc3f30..152c294 100644 (file)
@@ -122,7 +122,7 @@ abstract class Reader
                for i in [0 .. max[ do
                        var b = raw_read_byte
                        if b < 0 then break
-                       buf[i] = b.to_b
+                       buf[i] = b
                        rd += 1
                end
                return rd
@@ -551,7 +551,7 @@ abstract class Writer
        fun write(s: Text) is abstract
 
        # Write a single byte
-       fun write_byte(value: Byte) is abstract
+       fun write_byte(value: Int) is abstract
 
        # Write a single char
        fun write_char(c: Char) do
@@ -574,17 +574,32 @@ interface Writable
        # The specific logic it let to the concrete subclasses
        fun write_to(stream: Writer) is abstract
 
-       # Like `write_to` but return a new String (may be quite large)
+       # Like `write_to` but return a new String (may be quite large).
        #
-       # This funtionality is anectodical, since the point
-       # of streamable object to to be efficienlty written to a
-       # stream without having to allocate and concatenate strings
+       # This functionality is anecdotal, since the point
+       # of a streamable object is to be efficiently written to a
+       # stream without having to allocate and concatenate strings.
        fun write_to_string: String
        do
                var stream = new StringWriter
                write_to(stream)
                return stream.to_s
        end
+
+       # Like `write_to` but return a new Bytes (may be quite large)
+       #
+       # This functionality is anecdotal, since the point
+       # of a streamable object is to be efficiently written to a
+       # stream without having to allocate and concatenate buffers.
+       #
+       # Nevertheless, you might need this method if you want to know
+       # the byte size of a writable object.
+       fun write_to_bytes: Bytes
+       do
+               var stream = new BytesWriter
+               write_to(stream)
+               return stream.bytes
+       end
 end
 
 redef class Bytes
@@ -612,7 +627,7 @@ end
 #
 # writer.write "Strings "
 # writer.write_char '&'
-# writer.write_byte 0x20u8
+# writer.write_byte 0x20
 # writer.write_bytes "bytes".to_bytes
 #
 # assert writer.to_s == "\\x53\\x74\\x72\\x69\\x6E\\x67\\x73\\x20\\x26\\x20\\x62\\x79\\x74\\x65\\x73"
@@ -626,12 +641,12 @@ end
 # writer = new BytesWriter
 #
 # # Write just the character first half
-# writer.write_byte 0xC2u8
+# writer.write_byte 0xC2
 # assert writer.to_s == "\\xC2"
 # assert writer.bytes.to_s == "�"
 #
 # # Complete the character
-# writer.write_byte 0xA2u8
+# writer.write_byte 0xA2
 # assert writer.to_s == "\\xC2\\xA2"
 # assert writer.bytes.to_s == "¢"
 # ~~~
@@ -683,7 +698,7 @@ end
 #
 # writer.write "Strings "
 # writer.write_char '&'
-# writer.write_byte 0x20u8
+# writer.write_byte 0x20
 # writer.write_bytes "bytes".to_bytes
 #
 # assert writer.to_s == "Strings & bytes"
index 168225c..fbe045f 100644 (file)
@@ -34,34 +34,44 @@ abstract class Text
 
        # Gets a view on the chars of the Text object
        #
-       #     assert "hello".chars.to_a == ['h', 'e', 'l', 'l', 'o']
+       # ~~~
+       # assert "hello".chars.to_a == ['h', 'e', 'l', 'l', 'o']
+       # ~~~
        fun chars: SequenceRead[Char] is abstract
 
        # Gets a view on the bytes of the Text object
        #
-       #     assert "hello".bytes.to_a == [104u8, 101u8, 108u8, 108u8, 111u8]
-       fun bytes: SequenceRead[Byte] is abstract
+       # ~~~
+       # assert "hello".bytes.to_a == [104, 101, 108, 108, 111]
+       # ~~~
+       fun bytes: SequenceRead[Int] is abstract
 
        # Number of characters contained in self.
        #
-       #     assert "12345".length == 5
-       #     assert "".length == 0
-       #     assert "あいうえお".length == 5
+       # ~~~
+       # assert "12345".length == 5
+       # assert "".length == 0
+       # assert "あいうえお".length == 5
+       # ~~~
        fun length: Int is abstract
 
        # Number of bytes in `self`
        #
-       #     assert "12345".byte_length == 5
-       #     assert "あいうえお".byte_length == 15
+       # ~~~
+       # assert "12345".byte_length == 5
+       # assert "あいうえお".byte_length == 15
+       # ~~~
        fun byte_length: Int is abstract
 
        # Create a substring.
        #
-       #     assert "abcd".substring(1, 2)      ==  "bc"
-       #     assert "abcd".substring(-1, 2)     ==  "a"
-       #     assert "abcd".substring(1, 0)      ==  ""
-       #     assert "abcd".substring(2, 5)      ==  "cd"
-       #     assert "あいうえお".substring(1,3) ==  "いうえ"
+       # ~~~
+       # assert "abcd".substring(1, 2)      ==  "bc"
+       # assert "abcd".substring(-1, 2)     ==  "a"
+       # assert "abcd".substring(1, 0)      ==  ""
+       # assert "abcd".substring(2, 5)      ==  "cd"
+       # assert "あいうえお".substring(1,3) ==  "いうえ"
+       # ~~~
        #
        # A `from` index < 0 will be replaced by 0.
        # Unless a `count` value is > 0 at the same time.
@@ -73,8 +83,10 @@ abstract class Text
 
        # Is the current Text empty (== "")
        #
-       #     assert "".is_empty
-       #     assert not "foo".is_empty
+       # ~~~
+       # assert "".is_empty
+       # assert not "foo".is_empty
+       # ~~~
        fun is_empty: Bool do return self.length == 0
 
        # Returns an empty Text of the right type
@@ -87,37 +99,29 @@ abstract class Text
        fun to_buffer: Buffer is abstract
 
        # Gets the first char of the Text
-       #
-       # DEPRECATED : Use self.chars.first instead
        fun first: Char do return self.chars[0]
 
        # Access a character at `index` in the string.
        #
-       #     assert "abcd"[2]         == 'c'
-       #
-       # DEPRECATED : Use self.chars.[] instead
+       # ~~~
+       # assert "abcd"[2]         == 'c'
+       # ~~~
        fun [](index: Int): Char do return self.chars[index]
 
        # Gets the index of the first occurence of 'c'
        #
        # Returns -1 if not found
-       #
-       # DEPRECATED : Use self.chars.index_of instead
        fun index_of(c: Char): Int
        do
                return index_of_from(c, 0)
        end
 
        # Gets the last char of self
-       #
-       # DEPRECATED : Use self.chars.last instead
        fun last: Char do return self.chars[length-1]
 
        # Gets the index of the first occurence of ´c´ starting from ´pos´
        #
        # Returns -1 if not found
-       #
-       # DEPRECATED : Use self.chars.index_of_from instead
        fun index_of_from(c: Char, pos: Int): Int
        do
                var iter = self.chars.iterator_from(pos)
@@ -131,8 +135,6 @@ abstract class Text
        # Gets the last index of char ´c´
        #
        # Returns -1 if not found
-       #
-       # DEPRECATED : Use self.chars.last_index_of instead
        fun last_index_of(c: Char): Int
        do
                return last_index_of_from(c, length - 1)
@@ -143,24 +145,24 @@ abstract class Text
 
        # The index of the last occurrence of an element starting from pos (in reverse order).
        #
-       #     var s = "/etc/bin/test/test.nit"
-       #     assert s.last_index_of_from('/', s.length-1) == 13
-       #     assert s.last_index_of_from('/', 12)         == 8
+       # ~~~
+       # var s = "/etc/bin/test/test.nit"
+       # assert s.last_index_of_from('/', s.length-1) == 13
+       # assert s.last_index_of_from('/', 12)         == 8
+       # ~~~
        #
        # Returns -1 if not found
-       #
-       # DEPRECATED : Use self.chars.last_index_of_from instead
        fun last_index_of_from(item: Char, pos: Int): Int do return chars.last_index_of_from(item, pos)
 
        # Concatenates `o` to `self`
        #
-       #     assert "hello" + "world"  == "helloworld"
-       #     assert "" + "hello" + ""  == "hello"
+       # ~~~
+       # assert "hello" + "world"  == "helloworld"
+       # assert "" + "hello" + ""  == "hello"
+       # ~~~
        fun +(o: Text): SELFTYPE is abstract
 
        # Gets an iterator on the chars of self
-       #
-       # DEPRECATED : Use self.chars.iterator instead
        fun iterator: Iterator[Char]
        do
                return self.chars.iterator
@@ -168,15 +170,15 @@ abstract class Text
 
 
        # Gets an Array containing the chars of self
-       #
-       # DEPRECATED : Use self.chars.to_a instead
        fun to_a: Array[Char] do return chars.to_a
 
        # Create a substring from `self` beginning at the `from` position
        #
-       #     assert "abcd".substring_from(1)    ==  "bcd"
-       #     assert "abcd".substring_from(-1)   ==  "abcd"
-       #     assert "abcd".substring_from(2)    ==  "cd"
+       # ~~~
+       # assert "abcd".substring_from(1)    ==  "bcd"
+       # assert "abcd".substring_from(-1)   ==  "abcd"
+       # assert "abcd".substring_from(2)    ==  "cd"
+       # ~~~
        #
        # As with substring, a `from` index < 0 will be replaced by 0
        fun substring_from(from: Int): SELFTYPE
@@ -188,8 +190,10 @@ abstract class Text
 
        # Does self have a substring `str` starting from position `pos`?
        #
-       #     assert "abcd".has_substring("bc",1)            ==  true
-       #     assert "abcd".has_substring("bc",2)            ==  false
+       # ~~~
+       # assert "abcd".has_substring("bc",1)        ==  true
+       # assert "abcd".has_substring("bc",2)        ==  false
+       # ~~~
        #
        # Returns true iff all characters of `str` are presents
        # at the expected index in `self.`
@@ -198,13 +202,17 @@ abstract class Text
        #
        # This means that all characters of `str` need to be inside `self`.
        #
-       #     assert "abcd".has_substring("xab", -1)         == false
-       #     assert "abcd".has_substring("cdx", 2)          == false
+       # ~~~
+       # assert "abcd".has_substring("xab", -1)         == false
+       # assert "abcd".has_substring("cdx", 2)          == false
+       # ~~~
        #
        # And that the empty string is always a valid substring.
        #
-       #     assert "abcd".has_substring("", 2)             == true
-       #     assert "abcd".has_substring("", 200)           == true
+       # ~~~
+       # assert "abcd".has_substring("", 2)             == true
+       # assert "abcd".has_substring("", 200)           == true
+       # ~~~
        fun has_substring(str: String, pos: Int): Bool
        do
                if str.is_empty then return true
@@ -222,33 +230,41 @@ abstract class Text
 
        # Is this string prefixed by `prefix`?
        #
-       #     assert "abcd".has_prefix("ab")           ==  true
-       #     assert "abcbc".has_prefix("bc")          ==  false
-       #     assert "ab".has_prefix("abcd")           ==  false
+       # ~~~
+       # assert "abcd".has_prefix("ab")           ==  true
+       # assert "abcbc".has_prefix("bc")          ==  false
+       # assert "ab".has_prefix("abcd")           ==  false
+       # ~~~
        fun has_prefix(prefix: String): Bool do return has_substring(prefix,0)
 
        # Is this string suffixed by `suffix`?
        #
-       #     assert "abcd".has_suffix("abc")        ==  false
-       #     assert "abcd".has_suffix("bcd")        ==  true
+       # ~~~
+       # assert "abcd".has_suffix("abc")            ==  false
+       # assert "abcd".has_suffix("bcd")            ==  true
+       # ~~~
        fun has_suffix(suffix: String): Bool do return has_substring(suffix, length - suffix.length)
 
        # Returns `self` as the corresponding integer
        #
-       #     assert "123".to_i        == 123
-       #     assert "-1".to_i         == -1
-       #     assert "0x64".to_i       == 100
-       #     assert "0b1100_0011".to_i== 195
-       #     assert "--12".to_i       == 12
+       # ~~~
+       # assert "123".to_i        == 123
+       # assert "-1".to_i         == -1
+       # assert "0x64".to_i       == 100
+       # assert "0b1100_0011".to_i== 195
+       # assert "--12".to_i       == 12
+       # ~~~
        #
        # REQUIRE: `self`.`is_int`
        fun to_i: Int is abstract
 
        # If `self` contains a float, return the corresponding float
        #
-       #     assert "123".to_f        == 123.0
-       #     assert "-1".to_f         == -1.0
-       #     assert "-1.2e-3".to_f    == -0.0012
+       # ~~~
+       # assert "123".to_f        == 123.0
+       # assert "-1".to_f         == -1.0
+       # assert "-1.2e-3".to_f    == -0.0012
+       # ~~~
        fun to_f: Float
        do
                # Shortcut
@@ -257,7 +273,9 @@ abstract class Text
 
        # If `self` contains only digits and alpha <= 'f', return the corresponding integer.
        #
-       #     assert "ff".to_hex == 255
+       # ~~~
+       # assert "ff".to_hex == 255
+       # ~~~
        fun to_hex(pos, ln: nullable Int): Int do
                var res = 0
                if pos == null then pos = 0
@@ -272,22 +290,30 @@ abstract class Text
 
        # If `self` contains only digits <= '7', return the corresponding integer.
        #
-       #     assert "714".to_oct == 460
+       # ~~~
+       # assert "714".to_oct == 460
+       # ~~~
        fun to_oct: Int do return a_to(8)
 
        # If `self` contains only '0' et '1', return the corresponding integer.
        #
-       #     assert "101101".to_bin == 45
+       # ~~~
+       # assert "101101".to_bin == 45
+       # ~~~
        fun to_bin: Int do return a_to(2)
 
        # If `self` contains only digits '0' .. '9', return the corresponding integer.
        #
-       #     assert "108".to_dec == 108
+       # ~~~
+       # assert "108".to_dec == 108
+       # ~~~
        fun to_dec: Int do return a_to(10)
 
        # If `self` contains only digits and letters, return the corresponding integer in a given base
        #
-       #     assert "120".a_to(3)     == 15
+       # ~~~
+       # assert "120".a_to(3)     == 15
+       # ~~~
        fun a_to(base: Int) : Int
        do
                var i = 0
@@ -317,12 +343,14 @@ abstract class Text
 
        # Is this string in a valid numeric format compatible with `to_f`?
        #
-       #     assert "123".is_numeric  == true
-       #     assert "1.2".is_numeric  == true
-       #     assert "-1.2".is_numeric == true
-       #     assert "-1.23e-2".is_numeric == true
-       #     assert "1..2".is_numeric == false
-       #     assert "".is_numeric     == false
+       # ~~~
+       # assert "123".is_numeric  == true
+       # assert "1.2".is_numeric  == true
+       # assert "-1.2".is_numeric == true
+       # assert "-1.23e-2".is_numeric == true
+       # assert "1..2".is_numeric == false
+       # assert "".is_numeric     == false
+       # ~~~
        fun is_numeric: Bool
        do
                var has_point = false
@@ -345,9 +373,11 @@ abstract class Text
 
        # Returns `true` if the string contains only Hex chars
        #
-       #     assert "048bf".is_hex  == true
-       #     assert "ABCDEF".is_hex  == true
-       #     assert "0G".is_hex == false
+       # ~~~
+       # assert "048bf".is_hex  == true
+       # assert "ABCDEF".is_hex  == true
+       # assert "0G".is_hex == false
+       # ~~~
        fun is_hex: Bool
        do
                for i in [0..length[ do
@@ -361,8 +391,10 @@ abstract class Text
 
        # Returns `true` if the string contains only Binary digits
        #
-       #     assert "1101100".is_bin  == true
-       #     assert "1101020".is_bin  == false
+       # ~~~
+       # assert "1101100".is_bin  == true
+       # assert "1101020".is_bin  == false
+       # ~~~
        fun is_bin: Bool do
                for i in chars do if i != '0' and i != '1' then return false
                return true
@@ -370,8 +402,10 @@ abstract class Text
 
        # Returns `true` if the string contains only Octal digits
        #
-       #     assert "213453".is_oct  == true
-       #     assert "781".is_oct     == false
+       # ~~~
+       # assert "213453".is_oct  == true
+       # assert "781".is_oct     == false
+       # ~~~
        fun is_oct: Bool do
                for i in chars do if i < '0' or i > '7' then return false
                return true
@@ -379,8 +413,10 @@ abstract class Text
 
        # Returns `true` if the string contains only Decimal digits
        #
-       #     assert "10839".is_dec == true
-       #     assert "164F".is_dec  == false
+       # ~~~
+       # assert "10839".is_dec == true
+       # assert "164F".is_dec  == false
+       # ~~~
        fun is_dec: Bool do
                for i in chars do if i < '0' or i > '9' then return false
                return true
@@ -388,10 +424,12 @@ abstract class Text
 
        # Are all letters in `self` upper-case ?
        #
-       #     assert "HELLO WORLD".is_upper == true
-       #     assert "%$&%!".is_upper       == true
-       #     assert "hello world".is_upper == false
-       #     assert "Hello World".is_upper == false
+       # ~~~
+       # assert "HELLO WORLD".is_upper == true
+       # assert "%$&%!".is_upper       == true
+       # assert "hello world".is_upper == false
+       # assert "Hello World".is_upper == false
+       # ~~~
        fun is_upper: Bool
        do
                for i in [0..length[ do
@@ -403,9 +441,11 @@ abstract class Text
 
        # Are all letters in `self` lower-case ?
        #
-       #     assert "hello world".is_lower == true
-       #     assert "%$&%!".is_lower       == true
-       #     assert "Hello World".is_lower == false
+       # ~~~
+       # assert "hello world".is_lower == true
+       # assert "%$&%!".is_lower       == true
+       # assert "Hello World".is_lower == false
+       # ~~~
        fun is_lower: Bool
        do
                for i in [0..length[ do
@@ -417,7 +457,9 @@ abstract class Text
 
        # Removes the whitespaces at the beginning of self
        #
-       #     assert " \n\thello \n\t".l_trim == "hello \n\t"
+       # ~~~
+       # assert " \n\thello \n\t".l_trim == "hello \n\t"
+       # ~~~
        #
        # `Char::is_whitespace` determines what is a whitespace.
        fun l_trim: SELFTYPE
@@ -433,7 +475,9 @@ abstract class Text
 
        # Removes the whitespaces at the end of self
        #
-       #     assert " \n\thello \n\t".r_trim == " \n\thello"
+       # ~~~
+       # assert " \n\thello \n\t".r_trim == " \n\thello"
+       # ~~~
        #
        # `Char::is_whitespace` determines what is a whitespace.
        fun r_trim: SELFTYPE
@@ -449,17 +493,21 @@ abstract class Text
 
        # Trims trailing and preceding white spaces
        #
-       #     assert "  Hello  World !  ".trim   == "Hello  World !"
-       #     assert "\na\nb\tc\t".trim          == "a\nb\tc"
+       # ~~~
+       # assert "  Hello  World !  ".trim   == "Hello  World !"
+       # assert "\na\nb\tc\t".trim          == "a\nb\tc"
+       # ~~~
        #
        # `Char::is_whitespace` determines what is a whitespace.
        fun trim: SELFTYPE do return (self.l_trim).r_trim
 
        # Is the string non-empty but only made of whitespaces?
        #
-       #     assert " \n\t ".is_whitespace    == true
-       #     assert "  hello  ".is_whitespace == false
-       #     assert "".is_whitespace          == false
+       # ~~~
+       # assert " \n\t ".is_whitespace    == true
+       # assert "  hello  ".is_whitespace == false
+       # assert "".is_whitespace          == false
+       # ~~~
        #
        # `Char::is_whitespace` determines what is a whitespace.
        fun is_whitespace: Bool
@@ -473,19 +521,23 @@ abstract class Text
 
        # Returns `self` removed from its last line terminator (if any).
        #
-       #     assert "Hello\n".chomp == "Hello"
-       #     assert "Hello".chomp   == "Hello"
+       # ~~~
+       # assert "Hello\n".chomp == "Hello"
+       # assert "Hello".chomp   == "Hello"
        #
-       #     assert "\n".chomp == ""
-       #     assert "".chomp   == ""
+       # assert "\n".chomp == ""
+       # assert "".chomp   == ""
+       # ~~~
        #
        # Line terminators are `"\n"`, `"\r\n"` and `"\r"`.
        # A single line terminator, the last one, is removed.
        #
-       #     assert "\r\n".chomp     == ""
-       #     assert "\r\n\n".chomp   == "\r\n"
-       #     assert "\r\n\r\n".chomp == "\r\n"
-       #     assert "\r\n\r".chomp   == "\r\n"
+       # ~~~
+       # assert "\r\n".chomp     == ""
+       # assert "\r\n\n".chomp   == "\r\n"
+       # assert "\r\n\r\n".chomp == "\r\n"
+       # assert "\r\n\r".chomp   == "\r\n"
+       # ~~~
        #
        # Note: unlike with most IO methods like `Reader::read_line`,
        # a single `\r` is considered here to be a line terminator and will be removed.
@@ -516,14 +568,18 @@ abstract class Text
        #
        # Examples
        #
-       #     assert "hello".justify(10, 0.0)  == "hello     "
-       #     assert "hello".justify(10, 1.0)  == "     hello"
-       #     assert "hello".justify(10, 0.5)  == "  hello   "
-       #     assert "hello".justify(10, 0.5, '.') == "..hello..."
+       # ~~~
+       # assert "hello".justify(10, 0.0)  == "hello     "
+       # assert "hello".justify(10, 1.0)  == "     hello"
+       # assert "hello".justify(10, 0.5)  == "  hello   "
+       # assert "hello".justify(10, 0.5, '.') == "..hello..."
+       # ~~~
        #
        # If `length` is not enough, `self` is returned as is.
        #
-       #     assert "hello".justify(2, 0.0)   == "hello"
+       # ~~~
+       # assert "hello".justify(2, 0.0)   == "hello"
+       # ~~~
        #
        # REQUIRE: `left >= 0.0 and left <= 1.0`
        # ENSURE: `self.length <= length implies result.length == length`
@@ -548,13 +604,17 @@ abstract class Text
        # * Never ends with an underscore.
        # * Never contains two contiguous underscores.
        #
-       #     assert "42_is/The answer!".to_cmangle == "_52d2_is_47dThe_32danswer_33d"
-       #     assert "__".to_cmangle == "_95d_95d"
-       #     assert "__d".to_cmangle == "_95d_d"
-       #     assert "_d_".to_cmangle == "_d_95d"
-       #     assert "_42".to_cmangle == "_95d42"
-       #     assert "foo".to_cmangle == "foo"
-       #     assert "".to_cmangle == ""
+       # Examples:
+       #
+       # ~~~
+       # assert "42_is/The answer!".to_cmangle == "_52d2_is_47dThe_32danswer_33d"
+       # assert "__".to_cmangle == "_95d_95d"
+       # assert "__d".to_cmangle == "_95d_d"
+       # assert "_d_".to_cmangle == "_d_95d"
+       # assert "_42".to_cmangle == "_95d42"
+       # assert "foo".to_cmangle == "foo"
+       # assert "".to_cmangle == ""
+       # ~~~
        fun to_cmangle: String
        do
                if is_empty then return ""
@@ -602,17 +662,21 @@ abstract class Text
 
        # Escape `"` `\` `'`, trigraphs and non printable characters using the rules of literal C strings and characters
        #
-       #     assert "abAB12<>&".escape_to_c       == "abAB12<>&"
-       #     assert "\n\"'\\".escape_to_c         == "\\n\\\"\\'\\\\"
-       #     assert "allo???!".escape_to_c        == "allo??\\?!"
-       #     assert "??=??/??'??(??)".escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
-       #     assert "??!??<??>??-".escape_to_c    == "?\\?!?\\?<?\\?>?\\?-"
+       # ~~~
+       # assert "abAB12<>&".escape_to_c       == "abAB12<>&"
+       # assert "\n\"'\\".escape_to_c         == "\\n\\\"\\'\\\\"
+       # assert "allo???!".escape_to_c        == "allo??\\?!"
+       # assert "??=??/??'??(??)".escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
+       # assert "??!??<??>??-".escape_to_c    == "?\\?!?\\?<?\\?>?\\?-"
+       # ~~~
        #
        # Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
        # Three digits are always used to avoid following digits to be interpreted as an element
        # of the octal sequence.
        #
-       #     assert "{0.code_point}{1.code_point}{8.code_point}{31.code_point}{32.code_point}".escape_to_c == "\\000\\001\\010\\037 "
+       # ~~~
+       # assert "{0.code_point}{1.code_point}{8.code_point}{31.code_point}{32.code_point}".escape_to_c == "\\000\\001\\010\\037 "
+       # ~~~
        #
        # The exceptions are the common `\t` and `\n`.
        fun escape_to_c: String
@@ -670,8 +734,10 @@ abstract class Text
        # Escape additionnal characters
        # The result might no be legal in C but be used in other languages
        #
-       #     assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
-       #     assert "allo???!".escape_more_to_c("")     == "allo??\\?!"
+       # ~~~
+       # assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
+       # assert "allo???!".escape_more_to_c("")     == "allo??\\?!"
+       # ~~~
        fun escape_more_to_c(chars: String): String
        do
                var b = new Buffer
@@ -686,14 +752,18 @@ abstract class Text
 
        # Escape to C plus braces
        #
-       #     assert "\n\"'\\\{\}".escape_to_nit      == "\\n\\\"\\'\\\\\\\{\\\}"
+       # ~~~
+       # assert "\n\"'\\\{\}".escape_to_nit      == "\\n\\\"\\'\\\\\\\{\\\}"
+       # ~~~
        fun escape_to_nit: String do return escape_more_to_c("\{\}")
 
        # Escape to POSIX Shell (sh).
        #
        # Abort if the text contains a null byte.
        #
-       #     assert "\n\"'\\\{\}0".escape_to_sh == "'\n\"'\\''\\\{\}0'"
+       # ~~~
+       # assert "\n\"'\\\{\}0".escape_to_sh == "'\n\"'\\''\\\{\}0'"
+       # ~~~
        fun escape_to_sh: String do
                var b = new Buffer
                b.chars.add '\''
@@ -724,7 +794,7 @@ abstract class Text
                        else if c == ':' or c == ' ' or c == '#' then
                                b.add('\\')
                                b.add(c)
-                       else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then
+                       else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' then
                                b.append("?{c.code_point.to_base(16)}")
                        else
                                b.add(c)
@@ -735,11 +805,13 @@ abstract class Text
 
        # Return a string where Nit escape sequences are transformed.
        #
-       #     var s = "\\n"
-       #     assert s.length        ==  2
-       #     var u = s.unescape_nit
-       #     assert u.length        ==  1
-       #     assert u.chars[0].code_point      ==  10 # (the ASCII value of the "new line" character)
+       # ~~~
+       # var s = "\\n"
+       # assert s.length        ==  2
+       # var u = s.unescape_nit
+       # assert u.length        ==  1
+       # assert u.chars[0].code_point      ==  10 # (the ASCII value of the "new line" character)
+       # ~~~
        fun unescape_nit: String
        do
                var res = new Buffer.with_cap(self.length)
@@ -772,7 +844,9 @@ abstract class Text
 
        # Returns `self` with all characters escaped with their UTF-16 representation
        #
-       #     assert "Aèあ𐏓".escape_to_utf16 == "\\u0041\\u00e8\\u3042\\ud800\\udfd3"
+       # ~~~
+       # assert "Aèあ𐏓".escape_to_utf16 == "\\u0041\\u00e8\\u3042\\ud800\\udfd3"
+       # ~~~
        fun escape_to_utf16: String do
                var buf = new Buffer
                for i in chars do buf.append i.escape_to_utf16
@@ -781,10 +855,12 @@ abstract class Text
 
        # Returns the Unicode char escaped by `self`
        #
-       #     assert "\\u0041".from_utf16_escape == 'A'
-       #     assert "\\ud800\\udfd3".from_utf16_escape == '𐏓'
-       #     assert "\\u00e8".from_utf16_escape == 'è'
-       #     assert "\\u3042".from_utf16_escape == 'あ'
+       # ~~~
+       # assert "\\u0041".from_utf16_escape == 'A'
+       # assert "\\ud800\\udfd3".from_utf16_escape == '𐏓'
+       # assert "\\u00e8".from_utf16_escape == 'è'
+       # assert "\\u3042".from_utf16_escape == 'あ'
+       # ~~~
        fun from_utf16_escape(pos, ln: nullable Int): Char do
                if pos == null then pos = 0
                if ln == null then ln = length - pos
@@ -805,9 +881,11 @@ abstract class Text
 
        # Returns a UTF-16 escape value
        #
-       #     var s = "\\ud800\\udfd3"
-       #     assert s.from_utf16_digit(2) == 0xD800
-       #     assert s.from_utf16_digit(8) == 0xDFD3
+       # ~~~
+       # var s = "\\ud800\\udfd3"
+       # assert s.from_utf16_digit(2) == 0xD800
+       # assert s.from_utf16_digit(8) == 0xDFD3
+       # ~~~
        fun from_utf16_digit(pos: nullable Int): Int do
                if pos == null then pos = 0
                return to_hex(pos, 4)
@@ -815,10 +893,12 @@ abstract class Text
 
        # Encode `self` to percent (or URL) encoding
        #
-       #     assert "aBc09-._~".to_percent_encoding == "aBc09-._~"
-       #     assert "%()< >".to_percent_encoding == "%25%28%29%3c%20%3e"
-       #     assert ".com/post?e=asdf&f=123".to_percent_encoding == ".com%2fpost%3fe%3dasdf%26f%3d123"
-       #     assert "éあいう".to_percent_encoding == "%c3%a9%e3%81%82%e3%81%84%e3%81%86"
+       # ~~~
+       # assert "aBc09-._~".to_percent_encoding == "aBc09-._~"
+       # assert "%()< >".to_percent_encoding == "%25%28%29%3c%20%3e"
+       # assert ".com/post?e=asdf&f=123".to_percent_encoding == ".com%2fpost%3fe%3dasdf%26f%3d123"
+       # assert "éあいう".to_percent_encoding == "%c3%a9%e3%81%82%e3%81%84%e3%81%86"
+       # ~~~
        fun to_percent_encoding: String
        do
                var buf = new Buffer
@@ -845,14 +925,16 @@ abstract class Text
        #
        # Invalid '%' are not decoded.
        #
-       #     assert "aBc09-._~".from_percent_encoding == "aBc09-._~"
-       #     assert "%25%28%29%3c%20%3e".from_percent_encoding == "%()< >"
-       #     assert ".com%2fpost%3fe%3dasdf%26f%3d123".from_percent_encoding == ".com/post?e=asdf&f=123"
-       #     assert "%25%28%29%3C%20%3E".from_percent_encoding == "%()< >"
-       #     assert "incomplete %".from_percent_encoding == "incomplete %"
-       #     assert "invalid % usage".from_percent_encoding == "invalid % usage"
-       #     assert "%c3%a9%e3%81%82%e3%81%84%e3%81%86".from_percent_encoding == "éあいう"
-       #     assert "%1 %A %C3%A9A9".from_percent_encoding == "%1 %A éA9"
+       # ~~~
+       # assert "aBc09-._~".from_percent_encoding == "aBc09-._~"
+       # assert "%25%28%29%3c%20%3e".from_percent_encoding == "%()< >"
+       # assert ".com%2fpost%3fe%3dasdf%26f%3d123".from_percent_encoding == ".com/post?e=asdf&f=123"
+       # assert "%25%28%29%3C%20%3E".from_percent_encoding == "%()< >"
+       # assert "incomplete %".from_percent_encoding == "incomplete %"
+       # assert "invalid % usage".from_percent_encoding == "invalid % usage"
+       # assert "%c3%a9%e3%81%82%e3%81%84%e3%81%86".from_percent_encoding == "éあいう"
+       # assert "%1 %A %C3%A9A9".from_percent_encoding == "%1 %A éA9"
+       # ~~~
        fun from_percent_encoding: String
        do
                var len = byte_length
@@ -875,21 +957,21 @@ abstract class Text
                        if c == '%' then
                                if i + 2 >= length then
                                        # What follows % has been cut off
-                                       buf[l] = '%'.ascii
+                                       buf[l] = u'%'
                                else
                                        i += 1
                                        var hex_s = substring(i, 2)
                                        if hex_s.is_hex then
                                                var hex_i = hex_s.to_hex
-                                               buf[l] = hex_i.to_b
+                                               buf[l] = hex_i
                                                i += 1
                                        else
                                                # What follows a % is not Hex
-                                               buf[l] = '%'.ascii
+                                               buf[l] = u'%'
                                                i -= 1
                                        end
                                end
-                       else buf[l] = c.ascii
+                       else buf[l] = c.code_point
 
                        i += 1
                        l += 1
@@ -900,7 +982,9 @@ abstract class Text
 
        # Escape the characters `<`, `>`, `&`, `"`, `'` and `/` as HTML/XML entity references.
        #
-       #     assert "a&b-<>\"x\"/'".html_escape      ==  "a&amp;b-&lt;&gt;&#34;x&#34;&#47;&#39;"
+       # ~~~
+       # assert "a&b-<>\"x\"/'".html_escape      ==  "a&amp;b-&lt;&gt;&#34;x&#34;&#47;&#39;"
+       # ~~~
        #
        # SEE: <https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content>
        fun html_escape: String
@@ -940,19 +1024,23 @@ abstract class Text
        # Equality of text
        # Two pieces of text are equals if thez have the same characters in the same order.
        #
-       #     assert "hello" == "hello"
-       #     assert "hello" != "HELLO"
-       #     assert "hello" == "hel"+"lo"
+       # ~~~
+       # assert "hello" == "hello"
+       # assert "hello" != "HELLO"
+       # assert "hello" == "hel"+"lo"
+       # ~~~
        #
        # Things that are not Text are not equal.
        #
-       #     assert "9" != '9'
-       #     assert "9" != ['9']
-       #     assert "9" != 9
+       # ~~~
+       # assert "9" != '9'
+       # assert "9" != ['9']
+       # assert "9" != 9
        #
-       #     assert "9".chars.first == '9'   # equality of Char
-       #     assert "9".chars       == ['9'] # equality of Sequence
-       #     assert "9".to_i        == 9     # equality of Int
+       # assert "9".chars.first == '9'   # equality of Char
+       # assert "9".chars       == ['9'] # equality of Sequence
+       # assert "9".to_i        == 9     # equality of Int
+       # ~~~
        redef fun ==(o)
        do
                if o == null then return false
@@ -964,8 +1052,10 @@ abstract class Text
 
        # Lexicographical comparaison
        #
-       #     assert "abc" < "xy"
-       #     assert "ABC" < "abc"
+       # ~~~
+       # assert "abc" < "xy"
+       # assert "ABC" < "abc"
+       # ~~~
        redef fun <(other)
        do
                var self_chars = self.chars.iterator
@@ -987,7 +1077,9 @@ abstract class Text
 
        # Escape string used in labels for graphviz
        #
-       #   assert ">><<".escape_to_dot == "\\>\\>\\<\\<"
+       # ~~~
+       # assert ">><<".escape_to_dot == "\\>\\>\\<\\<"
+       # ~~~
        fun escape_to_dot: String
        do
                return escape_more_to_c("|\{\}<>")
@@ -1016,8 +1108,10 @@ abstract class Text
        # The character `%` followed by something other than a number are left as is.
        # To represent a `%` followed by a number, double the `%`, as in `%%7`.
        #
-       #     assert "This %0 is a %1.".format("String", "formatted String") == "This String is a formatted String."
-       #     assert "Do not escape % nor %%1".format("unused") == "Do not escape % nor %1"
+       # ~~~
+       # assert "This %0 is a %1.".format("String", "formatted String") == "This String is a formatted String."
+       # assert "Do not escape % nor %%1".format("unused") == "Do not escape % nor %1"
+       # ~~~
        fun format(args: Object...): String do
                var s = new Array[Text]
                var curr_st = 0
@@ -1123,10 +1217,11 @@ abstract class Text
        #
        # REQUIRE: `n` must be large enough to contain `len` bytes
        #
-       #       var ns = new CString(8)
-       #       "Text is String".copy_to_native(ns, 8, 2, 0)
-       #       assert ns.to_s_with_length(8) == "xt is St"
-       #
+       # ~~~
+       # var ns = new CString(8)
+       # "Text is String".copy_to_native(ns, 8, 2, 0)
+       # assert ns.to_s_with_length(8) == "xt is St"
+       # ~~~
        fun copy_to_native(dest: CString, n, src_offset, dest_offset: Int) do
                var mypos = src_offset
                var itspos = dest_offset
@@ -1141,7 +1236,7 @@ abstract class Text
        # Packs the content of a string in packs of `ln` chars.
        # This variant ensures that only the last element might be smaller than `ln`
        #
-       # ~~~nit
+       # ~~~
        # var s = "abcdefghijklmnopqrstuvwxyz"
        # assert s.pack_l(4) == ["abcd","efgh","ijkl","mnop","qrst","uvwx","yz"]
        # ~~~
@@ -1158,7 +1253,7 @@ abstract class Text
        # Packs the content of a string in packs of `ln` chars.
        # This variant ensures that only the first element might be smaller than `ln`
        #
-       # ~~~nit
+       # ~~~
        # var s = "abcdefghijklmnopqrstuvwxyz"
        # assert s.pack_r(4) == ["ab","cdef","ghij","klmn","opqr","stuv","wxyz"]
        # ~~~
@@ -1174,83 +1269,107 @@ abstract class Text
 
        # Concatenates self `i` times
        #
-       #~~~nit
-       #       assert "abc" * 4 == "abcabcabcabc"
-       #       assert "abc" * 1 == "abc"
-       #       assert "abc" * 0 == ""
-       #       var b = new Buffer
-       #       b.append("天地")
-       #       b = b * 4
-       #       assert b == "天地天地天地天地"
-       #~~~
+       # ~~~
+       # assert "abc" * 4 == "abcabcabcabc"
+       # assert "abc" * 1 == "abc"
+       # assert "abc" * 0 == ""
+       # var b = new Buffer
+       # b.append("天地")
+       # b = b * 4
+       # assert b == "天地天地天地天地"
+       # ~~~
        fun *(i: Int): SELFTYPE is abstract
 
        # Insert `s` at `pos`.
        #
-       #~~~nit
-       #       assert "helloworld".insert_at(" ", 5)   == "hello world"
-       #       var b = new Buffer
-       #       b.append("Hello世界")
-       #       b = b.insert_at(" beautiful ", 5)
-       #       assert b == "Hello beautiful 世界"
-       #~~~
+       # ~~~
+       # assert "helloworld".insert_at(" ", 5) == "hello world"
+       # var b = new Buffer
+       # b.append("Hello世界")
+       # b = b.insert_at(" beautiful ", 5)
+       # assert b == "Hello beautiful 世界"
+       # ~~~
        fun insert_at(s: String, pos: Int): SELFTYPE is abstract
 
        # Returns a reversed version of self
        #
-       #     assert "hello".reversed  == "olleh"
-       #     assert "bob".reversed    == "bob"
-       #     assert "".reversed       == ""
+       # ~~~
+       # assert "hello".reversed  == "olleh"
+       # assert "bob".reversed    == "bob"
+       # assert "".reversed       == ""
+       # ~~~
        fun reversed: SELFTYPE is abstract
 
        # A upper case version of `self`
        #
-       #     assert "Hello World!".to_upper     == "HELLO WORLD!"
+       # ~~~
+       # assert "Hello World!".to_upper     == "HELLO WORLD!"
+       # ~~~
        fun to_upper: SELFTYPE is abstract
 
        # A lower case version of `self`
        #
-       #     assert "Hello World!".to_lower     == "hello world!"
+       # ~~~
+       # assert "Hello World!".to_lower     == "hello world!"
+       # ~~~
        fun to_lower : SELFTYPE is abstract
 
        # Takes a camel case `self` and converts it to snake case
        #
-       #     assert "randomMethodId".to_snake_case == "random_method_id"
+       # ~~~
+       # assert "randomMethodId".to_snake_case == "random_method_id"
+       # ~~~
        #
        # The rules are the following:
        #
        # An uppercase is always converted to a lowercase
        #
-       #     assert "HELLO_WORLD".to_snake_case == "hello_world"
+       # ~~~
+       # assert "HELLO_WORLD".to_snake_case == "hello_world"
+       # ~~~
        #
        # An uppercase that follows a lowercase is prefixed with an underscore
        #
-       #     assert "HelloTheWORLD".to_snake_case == "hello_the_world"
+       # ~~~
+       # assert "HelloTheWORLD".to_snake_case == "hello_the_world"
+       # ~~~
        #
        # An uppercase that follows an uppercase and is followed by a lowercase, is prefixed with an underscore
        #
-       #     assert "HelloTHEWorld".to_snake_case == "hello_the_world"
+       # ~~~
+       # assert "HelloTHEWorld".to_snake_case == "hello_the_world"
+       # ~~~
        #
        # All other characters are kept as is; `self` does not need to be a proper CamelCased string.
        #
-       #     assert "=-_H3ll0Th3W0rld_-=".to_snake_case == "=-_h3ll0th3w0rld_-="
+       # ~~~
+       # assert "=-_H3ll0Th3W0rld_-=".to_snake_case == "=-_h3ll0th3w0rld_-="
+       # ~~~
        fun to_snake_case: SELFTYPE is abstract
 
        # Takes a snake case `self` and converts it to camel case
        #
-       #     assert "random_method_id".to_camel_case == "randomMethodId"
+       # ~~~
+       # assert "random_method_id".to_camel_case == "randomMethodId"
+       # ~~~
        #
        # If the identifier is prefixed by an underscore, the underscore is ignored
        #
-       #     assert "_private_field".to_camel_case == "_privateField"
+       # ~~~
+       # assert "_private_field".to_camel_case == "_privateField"
+       # ~~~
        #
        # If `self` is upper, it is returned unchanged
        #
-       #     assert "RANDOM_ID".to_camel_case == "RANDOM_ID"
+       # ~~~
+       # assert "RANDOM_ID".to_camel_case == "RANDOM_ID"
+       # ~~~
        #
        # If there are several consecutive underscores, they are considered as a single one
        #
-       #     assert "random__method_id".to_camel_case == "randomMethodId"
+       # ~~~
+       # assert "random__method_id".to_camel_case == "randomMethodId"
+       # ~~~
        fun to_camel_case: SELFTYPE is abstract
 
        # Returns a capitalized `self`
@@ -1262,10 +1381,12 @@ abstract class Text
        #
        # SEE : `Char::is_letter` for the definition of letter.
        #
-       #     assert "jAVASCRIPT".capitalized == "Javascript"
-       #     assert "i am root".capitalized == "I Am Root"
-       #     assert "ab_c -ab0c ab\nc".capitalized == "Ab_C -Ab0C Ab\nC"
-       #     assert "preserve my ACRONYMS".capitalized(keep_upper=true) == "Preserve My ACRONYMS"
+       # ~~~
+       # assert "jAVASCRIPT".capitalized == "Javascript"
+       # assert "i am root".capitalized == "I Am Root"
+       # assert "ab_c -ab0c ab\nc".capitalized == "Ab_C -Ab0C Ab\nC"
+       # assert "preserve my ACRONYMS".capitalized(keep_upper=true) == "Preserve My ACRONYMS"
+       # ~~~
        fun capitalized(keep_upper: nullable Bool): SELFTYPE do
                if length == 0 then return self
 
@@ -1341,7 +1462,7 @@ end
 # Abstract class for the SequenceRead compatible
 # views on the bytes of any Text
 private abstract class StringByteView
-       super SequenceRead[Byte]
+       super SequenceRead[Int]
 
        type SELFTYPE: Text
 
@@ -1360,7 +1481,9 @@ end
 #
 # String objects may be created using literals.
 #
-#     assert "Hello World!" isa String
+# ~~~
+# assert "Hello World!" isa String
+# ~~~
 abstract class String
        super Text
 
@@ -1419,18 +1542,16 @@ abstract class Buffer
        protected var written = false
 
        # Modifies the char contained at pos `index`
-       #
-       # DEPRECATED : Use self.chars.[]= instead
        fun []=(index: Int, item: Char) is abstract
 
        redef fun to_buffer do return clone
 
-       #~~~nit
-       #       var b = new Buffer
-       #       b.append("Buffer!")
-       #       var c = b.clone
-       #       assert b == c
-       #~~~
+       # ~~~
+       # var b = new Buffer
+       # b.append("Buffer!")
+       # var c = b.clone
+       # assert b == c
+       # ~~~
        redef fun clone do
                var cln = new Buffer.with_cap(byte_length)
                cln.append self
@@ -1438,17 +1559,17 @@ abstract class Buffer
        end
 
        # Adds a char `c` at the end of self
-       #
-       # DEPRECATED : Use self.chars.add instead
        fun add(c: Char) is abstract
 
        # Clears the buffer
        #
-       #     var b = new Buffer
-       #     b.append "hello"
-       #     assert not b.is_empty
-       #     b.clear
-       #     assert b.is_empty
+       # ~~~
+       # var b = new Buffer
+       # b.append "hello"
+       # assert not b.is_empty
+       # b.clear
+       # assert b.is_empty
+       # ~~~
        fun clear is abstract
 
        # Enlarges the subsequent array containing the chars of self
@@ -1456,42 +1577,52 @@ abstract class Buffer
 
        # Adds the content of text `s` at the end of self
        #
-       #     var b = new Buffer
-       #     b.append "hello"
-       #     b.append "world"
-       #     assert b == "helloworld"
+       # ~~~
+       # var b = new Buffer
+       # b.append "hello"
+       # b.append "world"
+       # assert b == "helloworld"
+       # ~~~
        fun append(s: Text) is abstract
 
        # `self` is appended in such a way that `self` is repeated `r` times
        #
-       #     var b = new Buffer
-       #     b.append "hello"
-       #     b.times 3
-       #     assert b == "hellohellohello"
+       # ~~~
+       # var b = new Buffer
+       # b.append "hello"
+       # b.times 3
+       # assert b == "hellohellohello"
+       # ~~~
        fun times(r: Int) is abstract
 
        # Reverses itself in-place
        #
-       #     var b = new Buffer
-       #     b.append("hello")
-       #     b.reverse
-       #     assert b == "olleh"
+       # ~~~
+       # var b = new Buffer
+       # b.append("hello")
+       # b.reverse
+       # assert b == "olleh"
+       # ~~~
        fun reverse is abstract
 
        # Changes each lower-case char in `self` by its upper-case variant
        #
-       #     var b = new Buffer
-       #     b.append("Hello World!")
-       #     b.upper
-       #     assert b == "HELLO WORLD!"
+       # ~~~
+       # var b = new Buffer
+       # b.append("Hello World!")
+       # b.upper
+       # assert b == "HELLO WORLD!"
+       # ~~~
        fun upper is abstract
 
        # Changes each upper-case char in `self` by its lower-case variant
        #
-       #     var b = new Buffer
-       #     b.append("Hello World!")
-       #     b.lower
-       #     assert b == "hello world!"
+       # ~~~
+       # var b = new Buffer
+       # b.append("Hello World!")
+       # b.lower
+       # assert b == "hello world!"
+       # ~~~
        fun lower is abstract
 
        # Capitalizes each word in `self`
@@ -1508,23 +1639,25 @@ abstract class Buffer
        #
        # SEE: `Char::is_letter` for the definition of a letter.
        #
-       #     var b = new FlatBuffer.from("jAVAsCriPt")
-       #     b.capitalize
-       #     assert b == "Javascript"
-       #     b = new FlatBuffer.from("i am root")
-       #     b.capitalize
-       #     assert b == "I Am Root"
-       #     b = new FlatBuffer.from("ab_c -ab0c ab\nc")
-       #     b.capitalize
-       #     assert b == "Ab_C -Ab0C Ab\nC"
-       #
-       #     b = new FlatBuffer.from("12345")
-       #     b.capitalize(src="foo")
-       #     assert b == "Foo45"
-       #
-       #     b = new FlatBuffer.from("preserve my ACRONYMS")
-       #     b.capitalize(keep_upper=true)
-       #     assert b == "Preserve My ACRONYMS"
+       # ~~~
+       # var b = new FlatBuffer.from("jAVAsCriPt")
+       # b.capitalize
+       # assert b == "Javascript"
+       # b = new FlatBuffer.from("i am root")
+       # b.capitalize
+       # assert b == "I Am Root"
+       # b = new FlatBuffer.from("ab_c -ab0c ab\nc")
+       # b.capitalize
+       # assert b == "Ab_C -Ab0C Ab\nC"
+       #
+       # b = new FlatBuffer.from("12345")
+       # b.capitalize(src="foo")
+       # assert b == "Foo45"
+       #
+       # b = new FlatBuffer.from("preserve my ACRONYMS")
+       # b.capitalize(keep_upper=true)
+       # assert b == "Preserve My ACRONYMS"
+       # ~~~
        fun capitalize(keep_upper: nullable Bool, src: nullable Text) do
                src = src or else self
                var length = src.length
@@ -1555,16 +1688,16 @@ abstract class Buffer
 
        # Appends `length` chars from `s` starting at index `from`
        #
-       # ~~~nit
-       #       var b = new Buffer
-       #       b.append_substring("abcde", 1, 2)
-       #       assert b == "bc"
-       #       b.append_substring("vwxyz", 2, 3)
-       #       assert b == "bcxyz"
-       #       b.append_substring("ABCDE", 4, 300)
-       #       assert b == "bcxyzE"
-       #       b.append_substring("VWXYZ", 400, 1)
-       #       assert b == "bcxyzE"
+       # ~~~
+       # var b = new Buffer
+       # b.append_substring("abcde", 1, 2)
+       # assert b == "bc"
+       # b.append_substring("vwxyz", 2, 3)
+       # assert b == "bcxyz"
+       # b.append_substring("ABCDE", 4, 300)
+       # assert b == "bcxyzE"
+       # b.append_substring("VWXYZ", 400, 1)
+       # assert b == "bcxyzE"
        # ~~~
        fun append_substring(s: Text, from, length: Int) do
                if from < 0 then
@@ -1602,36 +1735,36 @@ abstract class Buffer
 
        # Inserts `s` at position `pos`
        #
-       #~~~nit
-       #       var b = new Buffer
-       #       b.append "美しい世界"
-       #       b.insert(" nit ", 3)
-       #       assert b == "美しい nit 世界"
-       #~~~
+       # ~~~
+       # var b = new Buffer
+       # b.append "美しい世界"
+       # b.insert(" nit ", 3)
+       # assert b == "美しい nit 世界"
+       # ~~~
        fun insert(s: Text, pos: Int) is abstract
 
        # Inserts `c` at position `pos`
        #
-       #~~~nit
-       #       var b = new Buffer
-       #       b.append "美しい世界"
-       #       b.insert_char(' ', 3)
-       #       assert b == "美しい 世界"
-       #~~~
+       # ~~~
+       # var b = new Buffer
+       # b.append "美しい世界"
+       # b.insert_char(' ', 3)
+       # assert b == "美しい 世界"
+       # ~~~
        fun insert_char(c: Char, pos: Int) is abstract
 
        # Removes a substring from `self` at position `pos`
        #
        # NOTE: `length` defaults to 1, expressed in chars
        #
-       #~~~nit
-       #       var b = new Buffer
-       #       b.append("美しい 世界")
-       #       b.remove_at(3)
-       #       assert b == "美しい世界"
-       #       b.remove_at(1, 2)
-       #       assert b == "美世界"
-       #~~~
+       # ~~~
+       # var b = new Buffer
+       # b.append("美しい 世界")
+       # b.remove_at(3)
+       # assert b == "美しい世界"
+       # b.remove_at(1, 2)
+       # assert b == "美世界"
+       # ~~~
        fun remove_at(pos: Int, length: nullable Int) is abstract
 
        redef fun reversed do
@@ -1758,7 +1891,9 @@ redef class Object
 
        # The class name of the object.
        #
-       #     assert 5.class_name == "Int"
+       # ~~~
+       # assert 5.class_name == "Int"
+       # ~~~
        fun class_name: String do return native_class_name.to_s
 
        # Developer readable representation of `self`.
@@ -1777,8 +1912,10 @@ redef class Object
 end
 
 redef class Bool
-       #     assert true.to_s         == "true"
-       #     assert false.to_s        == "false"
+       # ~~~
+       # assert true.to_s         == "true"
+       # assert false.to_s        == "false"
+       # ~~~
        redef fun to_s
        do
                if self then
@@ -1802,12 +1939,14 @@ redef class Byte
 
        # Displayable byte in its hexadecimal form (0x..)
        #
-       #     assert 1.to_b.to_s       == "0x01"
-       #     assert (-123).to_b.to_s  == "0x85"
+       # ~~~
+       # assert 1.to_b.to_s       == "0x01"
+       # assert (-123).to_b.to_s  == "0x85"
+       # ~~~
        redef fun to_s do
                var nslen = byte_to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_byte_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false, clean=false)
        end
@@ -1876,16 +2015,20 @@ redef class Int
 
        # return displayable int in hexadecimal
        #
-       #     assert 1.to_hex  == "1"
-       #     assert (-255).to_hex  == "-ff"
+       # ~~~
+       # assert 1.to_hex  == "1"
+       # assert (-255).to_hex  == "-ff"
+       # ~~~
        fun to_hex: String do return to_base(16)
 end
 
 redef class Float
        # Pretty representation of `self`, with decimals as needed from 1 to a maximum of 3
        #
-       #     assert 12.34.to_s       == "12.34"
-       #     assert (-0120.030).to_s == "-120.03"
+       # ~~~
+       # assert 12.34.to_s       == "12.34"
+       # assert (-0120.030).to_s == "-120.03"
+       # ~~~
        #
        # see `to_precision` for a custom precision.
        redef fun to_s do
@@ -1908,12 +2051,14 @@ redef class Float
 
        # `String` representation of `self` with the given number of `decimals`
        #
-       #     assert 12.345.to_precision(0)    == "12"
-       #     assert 12.345.to_precision(3)    == "12.345"
-       #     assert (-12.345).to_precision(3) == "-12.345"
-       #     assert (-0.123).to_precision(3)  == "-0.123"
-       #     assert 0.999.to_precision(2)     == "1.00"
-       #     assert 0.999.to_precision(4)     == "0.9990"
+       # ~~~
+       # assert 12.345.to_precision(0)    == "12"
+       # assert 12.345.to_precision(3)    == "12.345"
+       # assert (-12.345).to_precision(3) == "-12.345"
+       # assert (-0.123).to_precision(3)  == "-0.123"
+       # assert 0.999.to_precision(2)     == "1.00"
+       # assert 0.999.to_precision(4)     == "0.9990"
+       # ~~~
        fun to_precision(decimals: Int): String
        do
                if is_nan then return "nan"
@@ -1948,9 +2093,11 @@ redef class Char
 
        # Returns a sequence with the UTF-8 bytes of `self`
        #
-       #     assert 'a'.bytes == [0x61u8]
-       #     assert 'ま'.bytes == [0xE3u8, 0x81u8, 0xBEu8]
-       fun bytes: SequenceRead[Byte] do return to_s.bytes
+       # ~~~
+       # assert 'a'.bytes == [0x61]
+       # assert 'ま'.bytes == [0xE3, 0x81, 0xBE]
+       # ~~~
+       fun bytes: SequenceRead[Int] do return to_s.bytes
 
        # Is `self` an UTF-16 surrogate pair ?
        fun is_surrogate: Bool do
@@ -1981,7 +2128,9 @@ redef class Char
                return 1
        end
 
-       #     assert 'x'.to_s    == "x"
+       # ~~~
+       # assert 'x'.to_s    == "x"
+       # ~~~
        redef fun to_s do
                var ln = u8char_len
                var ns = new CString(ln + 1)
@@ -1994,10 +2143,12 @@ redef class Char
        # i.e. Represents `self`.`code_point` using UTF-16 codets escaped
        # with a `\u`
        #
-       #     assert 'A'.escape_to_utf16 == "\\u0041"
-       #     assert 'è'.escape_to_utf16 == "\\u00e8"
-       #     assert 'あ'.escape_to_utf16 == "\\u3042"
-       #     assert '𐏓'.escape_to_utf16 == "\\ud800\\udfd3"
+       # ~~~
+       # assert 'A'.escape_to_utf16 == "\\u0041"
+       # assert 'è'.escape_to_utf16 == "\\u00e8"
+       # assert 'あ'.escape_to_utf16 == "\\u3042"
+       # assert '𐏓'.escape_to_utf16 == "\\ud800\\udfd3"
+       # ~~~
        fun escape_to_utf16: String do
                var cp = code_point
                var buf: Buffer
@@ -2055,10 +2206,12 @@ redef class Char
 
        # Returns true if the char is a numerical digit
        #
-       #     assert '0'.is_numeric
-       #     assert '9'.is_numeric
-       #     assert not 'a'.is_numeric
-       #     assert not '?'.is_numeric
+       # ~~~
+       # assert '0'.is_numeric
+       # assert '9'.is_numeric
+       # assert not 'a'.is_numeric
+       # assert not '?'.is_numeric
+       # ~~~
        #
        # FIXME: Works on ASCII-range only
        fun is_numeric: Bool
@@ -2068,10 +2221,12 @@ redef class Char
 
        # Returns true if the char is an alpha digit
        #
-       #     assert 'a'.is_alpha
-       #     assert 'Z'.is_alpha
-       #     assert not '0'.is_alpha
-       #     assert not '?'.is_alpha
+       # ~~~
+       # assert 'a'.is_alpha
+       # assert 'Z'.is_alpha
+       # assert not '0'.is_alpha
+       # assert not '?'.is_alpha
+       # ~~~
        #
        # FIXME: Works on ASCII-range only
        fun is_alpha: Bool
@@ -2081,21 +2236,25 @@ redef class Char
 
        # Is `self` an hexadecimal digit ?
        #
-       #     assert 'A'.is_hexdigit
-       #     assert not 'G'.is_hexdigit
-       #     assert 'a'.is_hexdigit
-       #     assert not 'g'.is_hexdigit
-       #     assert '5'.is_hexdigit
+       # ~~~
+       # assert 'A'.is_hexdigit
+       # assert not 'G'.is_hexdigit
+       # assert 'a'.is_hexdigit
+       # assert not 'g'.is_hexdigit
+       # assert '5'.is_hexdigit
+       # ~~~
        fun is_hexdigit: Bool do return (self >= '0' and self <= '9') or (self >= 'A' and self <= 'F') or
                                        (self >= 'a' and self <= 'f')
 
        # Returns true if the char is an alpha or a numeric digit
        #
-       #     assert 'a'.is_alphanumeric
-       #     assert 'Z'.is_alphanumeric
-       #     assert '0'.is_alphanumeric
-       #     assert '9'.is_alphanumeric
-       #     assert not '?'.is_alphanumeric
+       # ~~~
+       # assert 'a'.is_alphanumeric
+       # assert 'Z'.is_alphanumeric
+       # assert '0'.is_alphanumeric
+       # assert '9'.is_alphanumeric
+       # assert not '?'.is_alphanumeric
+       # ~~~
        #
        # FIXME: Works on ASCII-range only
        fun is_alphanumeric: Bool
@@ -2152,13 +2311,17 @@ redef class Collection[E]
        #
        # Only concatenate if `separator == null`.
        #
-       #     assert [1, 2, 3].join(":")    == "1:2:3"
-       #     assert [1..3].join(":")       == "1:2:3"
-       #     assert [1..3].join            == "123"
+       # ~~~
+       # assert [1, 2, 3].join(":")    == "1:2:3"
+       # assert [1..3].join(":")       == "1:2:3"
+       # assert [1..3].join            == "123"
+       # ~~~
        #
        # if `last_separator` is given, then it is used to separate the last element.
        #
-       #     assert [1, 2, 3, 4].join(", ", " and ")    == "1, 2, 3 and 4"
+       # ~~~
+       # assert [1, 2, 3, 4].join(", ", " and ")    == "1, 2, 3 and 4"
+       # ~~~
        fun join(separator: nullable Text, last_separator: nullable Text): String
        do
                if is_empty then return ""
@@ -2193,10 +2356,12 @@ redef class Map[K,V]
        # Key and value are separated by `couple_sep`.
        # Couples are separated by `sep`.
        #
-       #     var m = new HashMap[Int, String]
-       #     m[1] = "one"
-       #     m[10] = "ten"
-       #     assert m.join("; ", "=") == "1=one; 10=ten"
+       # ~~~
+       # var m = new HashMap[Int, String]
+       # m[1] = "one"
+       # m[10] = "ten"
+       # assert m.join("; ", "=") == "1=one; 10=ten"
+       # ~~~
        fun join(sep, couple_sep: String): String is abstract
 end
 
@@ -2240,9 +2405,11 @@ end
 #
 # The comparaison call `to_s` on object and use the result to order things.
 #
-#     var a = [1, 2, 3, 10, 20]
-#     (new CachedAlphaComparator).sort(a)
-#     assert a == [1, 10, 2, 20, 3]
+# ~~~
+# var a = [1, 2, 3, 10, 20]
+# (new CachedAlphaComparator).sort(a)
+# assert a == [1, 10, 2, 20, 3]
+# ~~~
 #
 # Internally the result of `to_s` is cached in a HashMap to counter
 # uneficient implementation of `to_s`.
@@ -2282,9 +2449,11 @@ end
 # Note: the result of `to_s` is not cached, thus can be invoked a lot
 # on a single instace. See `CachedAlphaComparator` as an alternative.
 #
-#     var a = [1, 2, 3, 10, 20]
-#     alpha_comparator.sort(a)
-#     assert a == [1, 10, 2, 20, 3]
+# ~~~
+# var a = [1, 2, 3, 10, 20]
+# alpha_comparator.sort(a)
+# assert a == [1, 10, 2, 20, 3]
+# ~~~
 fun alpha_comparator: Comparator do return once new AlphaComparator
 
 # The arguments of the program as given by the OS
index 88a21a4..c738f91 100644 (file)
@@ -40,7 +40,7 @@ redef class Int8
        redef fun to_s do
                var nslen = to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false)
        end
@@ -63,7 +63,7 @@ redef class Int16
        redef fun to_s do
                var nslen = to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false)
        end
@@ -87,7 +87,7 @@ redef class UInt16
        redef fun to_s do
                var nslen = to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false)
        end
@@ -111,7 +111,7 @@ redef class Int32
        redef fun to_s do
                var nslen = to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false)
        end
@@ -135,7 +135,7 @@ redef class UInt32
        redef fun to_s do
                var nslen = to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_to_s(ns, nslen + 1)
                return ns.to_s_unsafe(nslen, copy=false)
        end
index b728e42..cc60978 100644 (file)
@@ -55,7 +55,7 @@ redef class FlatText
                var its = _items
 
                if dpos == 1 then
-                       if its[b] & 0x80u8 == 0x00u8 then
+                       if its[b] & 0x80 == 0x00 then
                                b += 1
                        else
                                b += its.length_of_char_at(b)
@@ -113,17 +113,17 @@ redef class FlatText
                var endlen = 0
                while pos <= max do
                        var c = its[pos]
-                       if c == b'<' then
+                       if c == u'<' then
                                endlen += 3
-                       else if c == b'>' then
+                       else if c == u'>' then
                                endlen += 3
-                       else if c == b'&' then
+                       else if c == u'&' then
                                endlen += 4
-                       else if c == b'"' then
+                       else if c == u'"' then
                                endlen += 4
-                       else if c == b'\'' then
+                       else if c == u'\'' then
                                endlen += 4
-                       else if c == 0x2Fu8 then
+                       else if c == 0x2F then
                                endlen += 4
                        end
                        pos += 1
@@ -146,45 +146,45 @@ redef class FlatText
                        # Special codes:
                        # Some HTML characters are used as meta-data, they need
                        # to be replaced by an HTML-Escaped equivalent
-                       if c == b'<' then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'l'
-                               nits[outpos + 2] = b't'
-                               nits[outpos + 3] = b';'
+                       if c == u'<' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'l'
+                               nits[outpos + 2] = u't'
+                               nits[outpos + 3] = u';'
                                outpos += 4
-                       else if c == b'>' then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'g'
-                               nits[outpos + 2] = b't'
-                               nits[outpos + 3] = b';'
+                       else if c == u'>' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'g'
+                               nits[outpos + 2] = u't'
+                               nits[outpos + 3] = u';'
                                outpos += 4
-                       else if c == b'&' then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'a'
-                               nits[outpos + 2] = b'm'
-                               nits[outpos + 3] = b'p'
-                               nits[outpos + 4] = b';'
+                       else if c == u'&' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'a'
+                               nits[outpos + 2] = u'm'
+                               nits[outpos + 3] = u'p'
+                               nits[outpos + 4] = u';'
                                outpos += 5
-                       else if c == b'"' then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'#'
-                               nits[outpos + 2] = b'3'
-                               nits[outpos + 3] = b'4'
-                               nits[outpos + 4] = b';'
+                       else if c == u'"' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'#'
+                               nits[outpos + 2] = u'3'
+                               nits[outpos + 3] = u'4'
+                               nits[outpos + 4] = u';'
                                outpos += 5
-                       else if c == b'\'' then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'#'
-                               nits[outpos + 2] = b'3'
-                               nits[outpos + 3] = b'9'
-                               nits[outpos + 4] = b';'
+                       else if c == u'\'' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'#'
+                               nits[outpos + 2] = u'3'
+                               nits[outpos + 3] = u'9'
+                               nits[outpos + 4] = u';'
                                outpos += 5
-                       else if c == 0x2Fu8 then
-                               nits[outpos] = b'&'
-                               nits[outpos + 1] = b'#'
-                               nits[outpos + 2] = b'4'
-                               nits[outpos + 3] = b'7'
-                               nits[outpos + 4] = b';'
+                       else if c == u'/' then
+                               nits[outpos] = u'&'
+                               nits[outpos + 1] = u'#'
+                               nits[outpos + 2] = u'4'
+                               nits[outpos + 3] = u'7'
+                               nits[outpos + 4] = u';'
                                outpos += 5
                        else
                                nits[outpos] = c
@@ -208,33 +208,33 @@ redef class FlatText
                var req_esc = 0
                while pos <= max do
                        var c = its[pos]
-                       if c == b'\n' then
+                       if c == u'\n' then
                                req_esc += 1
-                       else if c == b'\t' then
+                       else if c == u'\t' then
                                req_esc += 1
-                       else if c == b'"' then
+                       else if c == u'"' then
                                req_esc += 1
-                       else if c == b'\'' then
+                       else if c == u'\'' then
                                req_esc += 1
-                       else if c == b'\\' then
+                       else if c == u'\\' then
                                req_esc += 1
-                       else if c == 0x3Fu8 then
+                       else if c == u'?' then
                                var j = pos + 1
                                if j < length then
                                        var next = its[j]
                                        # We ignore `??'` because it will be escaped as `??\'`.
                                        if
-                                               next == 0x21u8 or
-                                               next == 0x28u8 or
-                                               next == 0x29u8 or
-                                               next == 0x2Du8 or
-                                               next == 0x2Fu8 or
-                                               next == 0x3Cu8 or
-                                               next == 0x3Du8 or
-                                               next == 0x3Eu8
+                                               next == 0x21 or
+                                               next == 0x28 or
+                                               next == 0x29 or
+                                               next == 0x2D or
+                                               next == 0x2F or
+                                               next == 0x3C or
+                                               next == 0x3D or
+                                               next == 0x3E
                                        then req_esc += 1
                                end
-                       else if c < 32u8 then
+                       else if c < 32 then
                                req_esc += 3
                        end
                        pos += 1
@@ -269,52 +269,52 @@ redef class FlatText
                        # * 0x22 => \"
                        # * 0x27 => \'
                        # * 0x5C => \\
-                       if c == b'\t' then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b't'
+                       if c == u'\t' then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u't'
                                opos += 2
-                       else if c == b'\n' then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b'n'
+                       else if c == u'\n' then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u'n'
                                opos += 2
-                       else if c == b'"' then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b'"'
+                       else if c == u'"' then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u'"'
                                opos += 2
-                       else if c == b'\'' then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b'\''
+                       else if c == u'\'' then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u'\''
                                opos += 2
-                       else if c == b'\\' then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b'\\'
+                       else if c == u'\\' then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u'\\'
                                opos += 2
-                       else if c == 0x3Fu8 then
+                       else if c == u'?' then
                                var j = pos + 1
                                if j < length then
                                        var next = its[j]
                                        # We ignore `??'` because it will be escaped as `??\'`.
                                        if
-                                               next == 0x21u8 or
-                                               next == 0x28u8 or
-                                               next == 0x29u8 or
-                                               next == 0x2Du8 or
-                                               next == 0x2Fu8 or
-                                               next == 0x3Cu8 or
-                                               next == 0x3Du8 or
-                                               next == 0x3Eu8
+                                               next == 0x21 or
+                                               next == 0x28 or
+                                               next == 0x29 or
+                                               next == 0x2D or
+                                               next == 0x2F or
+                                               next == 0x3C or
+                                               next == 0x3D or
+                                               next == 0x3E
                                        then
-                                               nns[opos] = 0x5Cu8
+                                               nns[opos] = 0x5C
                                                opos += 1
                                        end
                                end
-                               nns[opos] = 0x3Fu8
+                               nns[opos] = 0x3F
                                opos += 1
-                       else if c < 32u8 then
-                               nns[opos] = b'\\'
-                               nns[opos + 1] = b'0'
-                               nns[opos + 2] = ((c & 0x38u8) >> 3) + b'0'
-                               nns[opos + 3] = (c & 0x07u8) + b'0'
+                       else if c < 32 then
+                               nns[opos] = u'\\'
+                               nns[opos + 1] = u'0'
+                               nns[opos + 2] = ((c & 0x38) >> 3) + u'0'
+                               nns[opos + 3] = (c & 0x07) + u'0'
                                opos += 4
                        else
                                nns[opos] = c
@@ -339,7 +339,7 @@ redef class FlatText
                if dpos == 1 and index < len - 1 then
                        var its = _items
                        var c = its[b]
-                       if c & 0x80u8 == 0x00u8 then
+                       if c & 0x80 == 0x00 then
                                # We want the next, and current is easy.
                                # So next is easy to find!
                                b += 1
@@ -351,20 +351,20 @@ redef class FlatText
                else if dpos == -1 and index > 1 then
                        var its = _items
                        var c = its[b-1]
-                       if c & 0x80u8 == 0x00u8 then
+                       if c & 0x80 == 0x00 then
                                # We want the previous, and it is easy.
                                b -= 1
                                dpos = 0
                                _position = index
                                _bytepos = b
-                               return c.ascii
+                               return c.code_point
                        end
                end
                if dpos == 0 then
                        # We know what we want (+0 or +1) just get it now!
                        var its = _items
                        var c = its[b]
-                       if c & 0x80u8 == 0x00u8 then return c.ascii
+                       if c & 0x80 == 0x00 then return c.code_point
                        return items.char_at(b)
                end
 
@@ -379,7 +379,7 @@ redef class FlatText
                var i = char_to_byte_index(index)
                var items = _items
                var b = items[i]
-               if b & 0x80u8 == 0x00u8 then return b.ascii
+               if b & 0x80 == 0x00 then return b.code_point
                return items.char_at(i)
        end
 
@@ -395,7 +395,7 @@ redef class FlatText
                var max = pos + ln
                for i in [pos .. max[ do
                        res <<= 4
-                       res += its[i].ascii.from_hex
+                       res += its[i].code_point.from_hex
                end
                return res
        end
@@ -421,7 +421,7 @@ abstract class FlatString
                var blen = _byte_length
                var new_items = new CString(blen + 1)
                _items.copy_to(new_items, blen, _first_byte, 0)
-               new_items[blen] = 0u8
+               new_items[blen] = 0
                return new_items
        end
 
@@ -624,7 +624,7 @@ abstract class FlatString
                var its = _items
                var fb = _first_byte
                var ns = new CString(new_byte_length + 1)
-               ns[new_byte_length] = 0u8
+               ns[new_byte_length] = 0
                var offset = 0
                while i > 0 do
                        its.copy_to(ns, mybtlen, fb, offset)
@@ -696,7 +696,7 @@ private class ASCIIFlatString
 
        redef fun [](idx) do
                assert idx < _byte_length and idx >= 0
-               return _items[idx + _first_byte].ascii
+               return _items[idx + _first_byte].code_point
        end
 
        redef fun substring(from, count) do
@@ -729,7 +729,7 @@ private class ASCIIFlatString
                return new ASCIIFlatString.full_data(_items, count, from + _first_byte, count)
        end
 
-       redef fun fetch_char_at(i) do return _items[i + _first_byte].ascii
+       redef fun fetch_char_at(i) do return _items[i + _first_byte].code_point
 end
 
 private class FlatStringCharReverseIterator
@@ -784,7 +784,7 @@ private class FlatStringCharView
 end
 
 private class FlatStringByteReverseIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        var target: FlatString
 
@@ -810,7 +810,7 @@ private class FlatStringByteReverseIterator
 end
 
 private class FlatStringByteIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        var target: FlatString
 
@@ -1019,7 +1019,7 @@ class FlatBuffer
        do
                var bln = _byte_length
                var new_native = new CString(bln + 1)
-               new_native[bln] = 0u8
+               new_native[bln] = 0
                if _length > 0 then _items.copy_to(new_native, bln, 0, 0)
                return new_native
        end
@@ -1163,7 +1163,7 @@ class FlatBuffer
 end
 
 private class FlatBufferByteReverseIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        var target: FlatBuffer
 
@@ -1197,7 +1197,7 @@ private class FlatBufferByteView
 end
 
 private class FlatBufferByteIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        var target: FlatBuffer
 
@@ -1331,7 +1331,7 @@ redef class CString
                if copy and (str == null or str.items == self) then
                        var new_cstr = new CString(byte_length + 1)
                        copy_to(new_cstr, byte_length, 0, 0)
-                       new_cstr[byte_length] = 0u8
+                       new_cstr[byte_length] = 0
                        str = new FlatString.full(new_cstr, byte_length, 0, char_length)
                end
 
@@ -1359,7 +1359,7 @@ redef class CString
                        end
                        if rem == 0 then break
                        var b = self[pos]
-                       if b & 0x80u8 == 0x00u8 then
+                       if b & 0x80 == 0x00 then
                                pos += 1
                                chr_ln += 1
                                rem -= 1
@@ -1368,13 +1368,13 @@ redef class CString
                        var nxst = length_of_char_at(pos)
                        var ok_st: Bool
                        if nxst == 1 then
-                               ok_st = b & 0x80u8 == 0u8
+                               ok_st = b & 0x80 == 0
                        else if nxst == 2 then
-                               ok_st = b & 0xE0u8 == 0xC0u8
+                               ok_st = b & 0xE0 == 0xC0
                        else if nxst == 3 then
-                               ok_st = b & 0xF0u8 == 0xE0u8
+                               ok_st = b & 0xF0 == 0xE0
                        else
-                               ok_st = b & 0xF8u8 == 0xF0u8
+                               ok_st = b & 0xF8 == 0xF0
                        end
                        if not ok_st then
                                if replacements == null then replacements = new Array[Int]
@@ -1425,9 +1425,9 @@ redef class CString
                                var chkln = repl_pos - old_repl
                                copy_to(ret, chkln, old_repl, off)
                                off += chkln
-                               ret[off] = 0xEFu8
-                               ret[off + 1] = 0xBFu8
-                               ret[off + 2] = 0xBDu8
+                               ret[off] = 0xEF
+                               ret[off + 1] = 0xBF
+                               ret[off + 2] = 0xBD
                                old_repl = repl_pos + 1
                                off += 3
                        end
@@ -1442,22 +1442,22 @@ redef class CString
        private fun set_char_at(pos: Int, c: Char) do
                var cp = c.code_point
                if cp < 128 then
-                       self[pos] = cp.to_b
+                       self[pos] = cp
                        return
                end
                var ln = c.u8char_len
                if ln == 2 then
-                       self[pos] = (0xC0 | ((cp & 0x7C0) >> 6)).to_b
-                       self[pos + 1] = (0x80 | (cp & 0x3F)).to_b
+                       self[pos] = 0xC0 | ((cp & 0x7C0) >> 6)
+                       self[pos + 1] = 0x80 | (cp & 0x3F)
                else if ln == 3 then
-                       self[pos] = (0xE0 | ((cp & 0xF000) >> 12)).to_b
-                       self[pos + 1] = (0x80 | ((cp & 0xFC0) >> 6)).to_b
-                       self[pos + 2] = (0x80 | (cp & 0x3F)).to_b
+                       self[pos] = 0xE0 | ((cp & 0xF000) >> 12)
+                       self[pos + 1] = 0x80 | ((cp & 0xFC0) >> 6)
+                       self[pos + 2] = 0x80 | (cp & 0x3F)
                else if ln == 4 then
-                       self[pos] = (0xF0 | ((cp & 0x1C0000) >> 18)).to_b
-                       self[pos + 1] = (0x80 | ((cp & 0x3F000) >> 12)).to_b
-                       self[pos + 2] = (0x80 | ((cp & 0xFC0) >> 6)).to_b
-                       self[pos + 3] = (0x80 | (cp & 0x3F)).to_b
+                       self[pos] = 0xF0 | ((cp & 0x1C0000) >> 18)
+                       self[pos + 1] = 0x80 | ((cp & 0x3F000) >> 12)
+                       self[pos + 2] = 0x80 | ((cp & 0xFC0) >> 6)
+                       self[pos + 3] = 0x80 | (cp & 0x3F)
                end
        end
 end
@@ -1474,7 +1474,7 @@ redef class Int
 
                var nslen = int_to_s_len
                var ns = new CString(nslen + 1)
-               ns[nslen] = 0u8
+               ns[nslen] = 0
                native_int_to_s(ns, nslen + 1)
                return new FlatString.full(ns, nslen, 0, nslen)
        end
@@ -1507,7 +1507,7 @@ redef class Array[E]
                        mypos += 1
                end
                var ns = new CString(sl + 1)
-               ns[sl] = 0u8
+               ns[sl] = 0
                i = 0
                var off = 0
                while i < mypos do
@@ -1544,7 +1544,7 @@ redef class NativeArray[E]
                        mypos += 1
                end
                var ns = new CString(sl + 1)
-               ns[sl] = 0u8
+               ns[sl] = 0
                i = 0
                var off = 0
                while i < mypos do
index 74f5f3f..372ac5a 100644 (file)
@@ -35,16 +35,16 @@ in "C" `{
 #include <string.h>
 `}
 
-redef class Byte
+redef class Int
        # Gives the length of the UTF-8 char starting with `self`
        fun u8len: Int do
-               if self & 0b1000_0000u8 == 0u8 then
+               if self & 0b1000_0000 == 0 then
                        return 1
-               else if self & 0b1110_0000u8 == 0b1100_0000u8 then
+               else if self & 0b1110_0000 == 0b1100_0000 then
                        return 2
-               else if self & 0b1111_0000u8 == 0b1110_0000u8 then
+               else if self & 0b1111_0000 == 0b1110_0000 then
                        return 3
-               else if self & 0b1111_1000u8 == 0b1111_0000u8 then
+               else if self & 0b1111_1000 == 0b1111_0000 then
                        return 4
                else
                        return 1
@@ -54,16 +54,16 @@ redef class Byte
        # Is `self` a valid UTF-8 sequence start ?
        #
        # ~~~nit
-       # assert 0u8.is_valid_utf8_start
-       # assert 0xC0u8.is_valid_utf8_start
-       # assert 0xE0u8.is_valid_utf8_start
-       # assert 0xF0u8.is_valid_utf8_start
+       # assert 0.is_valid_utf8_start
+       # assert 0xC0.is_valid_utf8_start
+       # assert 0xE0.is_valid_utf8_start
+       # assert 0xF0.is_valid_utf8_start
        # ~~~
        fun is_valid_utf8_start: Bool do
-               if self & 0x80u8 == 0u8 then return true
-               if self & 0b1110_0000u8 == 0b1100_0000u8 then return true
-               if self & 0b1111_0000u8 == 0b1110_0000u8 then return true
-               if self & 0b1111_1000u8 == 0b1111_0000u8 then return true
+               if self & 0x80 == 0 then return true
+               if self & 0b1110_0000 == 0b1100_0000 then return true
+               if self & 0b1111_0000 == 0b1110_0000 then return true
+               if self & 0b1111_1000 == 0b1111_0000 then return true
                return false
        end
 end
@@ -104,10 +104,10 @@ extern class CString `{ char* `}
        fun fast_cstring(index: Int): CString is intern
 
        # Get char at `index`.
-       fun [](index: Int): Byte is intern
+       fun [](index: Int): Int is intern
 
        # Set char `item` at index.
-       fun []=(index: Int, item: Byte) is intern
+       fun []=(index: Int, item: Int) is intern
 
        # Copy `self` to `dest`.
        fun copy_to(dest: CString, length: Int, from: Int, to: Int) is intern
@@ -120,7 +120,7 @@ extern class CString `{ char* `}
        fun cstring_length: Int
        do
                var l = 0
-               while self[l] != 0u8 do l += 1
+               while self[l] != 0 do l += 1
                return l
        end
 
@@ -146,7 +146,7 @@ extern class CString `{ char* `}
        # ~~~
        fun char_at(pos: Int): Char do
                var c = self[pos]
-               if c & 0x80u8 == 0u8 then return c.ascii
+               if c & 0x80 == 0 then return c.code_point
                var b = fetch_4_hchars(pos)
                var ret = 0u32
                if b & 0xC00000u32 != 0x800000u32 then return 0xFFFD.code_point
@@ -179,13 +179,13 @@ extern class CString `{ char* `}
        # Gets the length of the character at position `pos` (1 if invalid sequence)
        fun length_of_char_at(pos: Int): Int do
                var c = self[pos]
-               if c & 0x80u8 == 0x00u8 then
+               if c & 0x80 == 0x00 then
                        return 1
-               else if c & 0xE0u8 == 0xC0u8 and self[pos + 1] & 0xC0u8 == 0x80u8 then
+               else if c & 0xE0 == 0xC0 and self[pos + 1] & 0xC0 == 0x80 then
                        return 2
-               else if c & 0xF0u8 == 0xE0u8 and self[pos + 1] & 0xC0u8 == 0x80u8 and self[pos + 2] & 0xC0u8 == 0x80u8 then
+               else if c & 0xF0 == 0xE0 and self[pos + 1] & 0xC0 == 0x80 and self[pos + 2] & 0xC0 == 0x80 then
                        return 3
-               else if c & 0xF8u8 == 0xF0u8 and self[pos + 1] & 0xC0u8 == 0x80u8 and self[pos + 2] & 0xC0u8 == 0x80u8 and self[pos + 3] & 0xC0u8 == 0x80u8 then
+               else if c & 0xF8 == 0xF0 and self[pos + 1] & 0xC0 == 0x80 and self[pos + 2] & 0xC0 == 0x80 and self[pos + 3] & 0xC0 == 0x80 then
                        return 4
                else
                        return 1
@@ -265,13 +265,13 @@ extern class CString `{ char* `}
        # ~~~raw
        #       assert "abc".items.find_beginning_of_char_at(2) == 2
        #       assert "か".items.find_beginning_of_char_at(1) == 0
-       #       assert [0x41u8, 233u8].to_s.items.find_beginning_of_char_at(1) == 1
+       #       assert [0x41, 233].to_s.items.find_beginning_of_char_at(1) == 1
        # ~~~
        fun find_beginning_of_char_at(pos: Int): Int do
                var endpos = pos
                var c = self[pos]
-               if c & 0x80u8 == 0x00u8 then return pos
-               while c & 0xC0u8 == 0x80u8 do
+               if c & 0x80 == 0x00 then return pos
+               while c & 0xC0 == 0x80 do
                        pos -= 1
                        c = self[pos]
                end
index ca846fd..ef0016c 100644 (file)
@@ -91,7 +91,7 @@ private class Concat
        redef fun to_cstring do
                var len = _byte_length
                var ns = new CString(len + 1)
-               ns[len] = 0u8
+               ns[len] = 0
                var off = 0
                for i in substrings do
                        var ilen = i._byte_length
@@ -331,7 +331,7 @@ end
 
 # A reverse iterator capable of working with `Rope` objects
 private class RopeByteReverseIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        # Current CString
        var ns: CString is noautoinit
@@ -372,7 +372,7 @@ end
 
 # Forward iterator on the bytes of a `Rope`
 private class RopeByteIterator
-       super IndexedIterator[Byte]
+       super IndexedIterator[Int]
 
        # Position in current `String`
        var pns: Int is noautoinit
index 8745c1a..6402969 100644 (file)
@@ -26,20 +26,20 @@ redef class SingleByteXorCipher
 
                # Accumulate best result
                var max = 0.0
-               var best = 0.to_b
+               var best = 0
 
                # Iterate on possible values for a byte
                var xor_b = new Bytes.with_capacity(1)
                for b in [0 .. 255] do
                        # Need `Bytes` to pass to xor
-                       xor_b[0] = b.to_b
+                       xor_b[0] = b
 
                        # Xor and evaluate result
                        var xored = ciphertext.xorcipher(xor_b)
                        var result = xored.to_s.english_scoring
                        if result > max then
                                max = result
-                               best = b.to_b
+                               best = b
                        end
                end
 
index e4a133c..7181928 100644 (file)
@@ -154,6 +154,56 @@ redef class Text
                end
                return arr.to_s
        end
+
+       # Vigenere encoder on ASCII letters.
+       #
+       # Only the letters in '[A-Za-z]' are encoded while keeping the case.
+       #
+       #     assert "Hello, World!".vigenere("abc") == "Hfnlp, Yosnd!"
+       #
+       # REQUIRE `key` contains only lowercases '[a-z]'
+       fun vigenere(key: String): String
+       do
+               var res = new Buffer
+               res.enlarge(length)
+               var i = 0
+               for c in self do
+                       var k = key[i%key.length]
+                       assert k >= 'a' and k <= 'z'
+                       if c.is_letter then
+                               var d = k.code_point - 'a'.code_point
+                               c = c.rot(d)
+                               i += 1
+                       end
+                       res.add c
+               end
+               return res.to_s
+       end
+
+       # Vigenere decoder on ASCII letters.
+       #
+       # Only the letters in '[A-Za-z]' are decoded while keeping the case.
+       #
+       #     assert "Hfnlp, Yosnd!".uvigenere("abc") == "Hello, World!"
+       #
+       # REQUIRE `key` contains only lowercases '[a-z]'
+       fun uvigenere(key: String): String
+       do
+               var res = new Buffer
+               res.enlarge(length)
+               var i = 0
+               for c in self do
+                       var k = key[i%key.length]
+                       assert k >= 'a' and k <= 'z'
+                       if c.is_letter then
+                               var d = k.code_point - 'a'.code_point
+                               c = c.rot(-d)
+                               i += 1
+                       end
+                       res.add c
+               end
+               return res.to_s
+       end
 end
 
 redef class Bytes
@@ -162,12 +212,12 @@ redef class Bytes
        #     assert "this is a test".to_bytes.hamming_distance("wokka wokka!!!".bytes) == 37
        #     assert "this is a test".to_bytes.hamming_distance("this is a test".bytes) == 0
        #
-       fun hamming_distance(other: SequenceRead[Byte]): Int do
+       fun hamming_distance(other: SequenceRead[Int]): Int do
                var diff = 0
                for idx in self.length.times do
                        var res_byte = self[idx] ^ other[idx]
                        for bit in [0..8[ do
-                               if res_byte & 1u8 == 1u8 then diff += 1
+                               if res_byte & 1 == 1 then diff += 1
                                res_byte = res_byte >> 1
                        end
                end
diff --git a/lib/crypto/bytes.nit b/lib/crypto/bytes.nit
new file mode 100644 (file)
index 0000000..287d782
--- /dev/null
@@ -0,0 +1,33 @@
+# 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.
+
+# Mix of utilities and services related to bytes
+module bytes
+
+redef class Bytes
+       # PKCS#7 padding.
+       #
+       # Extends `self` by appending the number of bytes of padding to the end of the block.
+       #
+       #     assert "YELLOW SUBMARINE".to_bytes.pkcs7(20) == "YELLOW SUBMARINE\x04\x04\x04\x04".to_bytes
+       fun pkcs7(blocksize: Int): Bytes
+       do
+               var mod = length % blocksize
+               if mod == 0 then return self
+               var pad = blocksize - mod
+               var byte = pad
+               for i in [0..pad[ do add byte
+               return self
+       end
+end
index 4709403..97d7cee 100644 (file)
@@ -17,3 +17,4 @@ module crypto
 
 import basic_ciphers
 import xor_ciphers
+import bytes
index 18de9fb..aaa18d1 100644 (file)
@@ -69,7 +69,7 @@ class SingleByteXorCipher
        super Cipher
 
        # Cryptographic key used in encryption and decryption.
-       var key: Byte = 0.to_b
+       var key: Int = 0
 
        redef fun encrypt do
                var key_bytes = new Bytes.with_capacity(1)
index 4383c2b..4987be2 100644 (file)
@@ -161,10 +161,10 @@ class CustomTexture
 
                # Simple conversion from [0.0..1.0] to [0..255]
                var bytes = [for c in color do (c*255.0).round.to_i.clamp(0, 255).to_bytes.last]
-               while bytes.length < 4 do bytes.add 255u8
+               while bytes.length < 4 do bytes.add 255
 
                var offset = 4*(x + y*width.to_i)
-               for i in [0..4[ do cpixels[offset+i] = bytes[i]
+               for i in [0..4[ do cpixels[offset+i] = bytes[i].to_b
 
                loaded = false
        end
@@ -177,12 +177,12 @@ class CustomTexture
        do
                # Simple conversion from [0.0..1.0] to [0..255]
                var bytes = [for c in color do (c*255.0).round.to_i.clamp(0, 255).to_bytes.last]
-               while bytes.length < 4 do bytes.add 255u8
+               while bytes.length < 4 do bytes.add 255
 
                var i = 0
                for x in [0..width.to_i[ do
                        for y in [0..height.to_i[ do
-                               for j in [0..4[ do cpixels[i+j] = bytes[j]
+                               for j in [0..4[ do cpixels[i+j] = bytes[j].to_b
                                i += 4
                        end
                end
index 041e753..18814ee 100644 (file)
@@ -18,17 +18,17 @@ Token can also be recovered from user config with `get_github_oauth`.
 
 [[doc: load_user]]
 [[doc: User]]
-[[list: User]]
+[[defs: User]]
 
 ### Retrieving repo data
 
 [[doc: load_repo]]
 [[doc: Repo]]
-[[list: Repo]]
+[[defs: Repo]]
 
 ### Other data
 
-[[list: github::api]]
+[[defs: github::api]]
 
 ### Advanced uses
 
@@ -68,4 +68,4 @@ GithubAPI can trigger different events depending on the hook configuration.
 
 [[doc: GithubEvent]]
 
-[[list: github::events]]
+[[defs: github::events]]
index cc3d6e2..3e12dd7 100644 (file)
@@ -72,7 +72,7 @@ class Link
        redef fun rendering do
                add "<a{render_css_classes} href=\"{href}\""
                var title = self.title
-               if title != null then add " title=\"{title.write_to_string}\""
+               if title != null then add " title=\"{title.html_escape}\""
                add ">{text}</a>"
        end
 end
index 0d25f10..2d42e16 100644 (file)
@@ -128,7 +128,7 @@ redef class FlatText
        redef fun json_need_escape do
                var its = items
                for i in [first_byte .. last_byte] do
-                       if its[i] == 0x5Cu8 then return true
+                       if its[i] == 0x5C then return true
                end
                return false
        end
index efd434f..ec7d290 100644 (file)
@@ -2,6 +2,7 @@
 #
 # Copyright 2013 Jean-Philippe Caissy <jpcaissy@piji.ca>
 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+# Copyright 2018 Matthieu Le Guellaut <leguellaut.matthieu@gmail.com>
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -38,6 +39,8 @@ in "C" `{
        #include <arpa/inet.h>
        #include <netinet/in.h>
        #include <netinet/ip.h>
+       #include <sys/un.h>
+       #include <unistd.h>
 
 // Protect callbacks for compatibility with light FFI
 #ifdef Connection_decr_ref
@@ -145,8 +148,6 @@ interface EventCallback
 end
 
 # Spawned to manage a specific connection
-#
-# TODO, use polls
 class Connection
        super Writer
 
@@ -366,7 +367,7 @@ extern class NativeBufferEvent `{ struct bufferevent * `}
        `}
 
        # Write the byte `value`
-       fun write_byte(value: Byte): Int `{
+       fun write_byte(value: Int): Int `{
                unsigned char byt = (unsigned char)value;
                return bufferevent_write(self, &byt, 1);
        `}
@@ -418,31 +419,49 @@ end
 # A listener acting on an interface and port, spawns `Connection` on new connections
 extern class ConnectionListener `{ struct evconnlistener * `}
 
-       private new bind_to(base: NativeEventBase, address: CString, port: Int, factory: ConnectionFactory)
+       private new bind_tcp(base: NativeEventBase, address: CString, port: Int, factory: ConnectionFactory)
        import ConnectionFactory.accept_connection, error_callback `{
 
-               struct sockaddr_in sin;
-               struct evconnlistener *listener;
                ConnectionFactory_incr_ref(factory);
 
                struct hostent *hostent = gethostbyname(address);
-
                if (!hostent) {
                        return NULL;
                }
 
-               memset(&sin, 0, sizeof(sin));
+               struct sockaddr_in sin = {0};
                sin.sin_family = hostent->h_addrtype;
                sin.sin_port = htons(port);
                memcpy( &(sin.sin_addr.s_addr), (const void*)hostent->h_addr, hostent->h_length );
 
-               listener = evconnlistener_new_bind(base,
+               struct evconnlistener *listener = evconnlistener_new_bind(base,
                        (evconnlistener_cb)accept_connection_cb, factory,
                        LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
                        (struct sockaddr*)&sin, sizeof(sin));
+               if (listener != NULL) {
+                       evconnlistener_set_error_cb(listener,
+                               (evconnlistener_errorcb)ConnectionListener_error_callback);
+               }
+
+               return listener;
+       `}
+
+       private new bind_unix(base: NativeEventBase, file: CString, factory: ConnectionFactory)
+       import ConnectionFactory.accept_connection, error_callback `{
+
+               ConnectionFactory_incr_ref(factory);
+
+               struct sockaddr_un sun = {0};
+               sun.sun_family = AF_UNIX;
+               strncpy(sun.sun_path, file, sizeof(sun.sun_path) - 1);
 
+               struct evconnlistener *listener = evconnlistener_new_bind(base,
+                       (evconnlistener_cb)accept_connection_cb, factory,
+                       LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
+                       (struct sockaddr*)&sun, sizeof(sun));
                if (listener != NULL) {
-                       evconnlistener_set_error_cb(listener, (evconnlistener_errorcb)ConnectionListener_error_callback);
+                       evconnlistener_set_error_cb(listener,
+                               (evconnlistener_errorcb)ConnectionListener_error_callback);
                }
 
                return listener;
@@ -451,15 +470,17 @@ extern class ConnectionListener `{ struct evconnlistener * `}
        # Get the `NativeEventBase` associated to `self`
        fun base: NativeEventBase `{ return evconnlistener_get_base(self); `}
 
-       # Callback method on listening error
-       fun error_callback do
+       # Callback on listening error
+       fun error_callback
+       do
                var cstr = evutil_socket_error_to_string(evutil_socket_error)
-               print_error "libevent error: '{cstr}'"
+               print_error "libevent error: {cstr}"
        end
 end
 
 # Factory to listen on sockets and create new `Connection`
 class ConnectionFactory
+
        # The `NativeEventBase` for the dispatch loop of this factory
        var event_base: NativeEventBase
 
@@ -490,17 +511,45 @@ class ConnectionFactory
                return new Connection(buffer_event)
        end
 
-       # Listen on `address`:`port` for new connection, which will callback `spawn_connection`
-       fun bind_to(address: String, port: Int): nullable ConnectionListener
+       # Listen on the TCP socket at `address`:`port` for new connections
+       #
+       # On new connections, libevent callbacks `spawn_connection`.
+       fun bind_tcp(address: String, port: Int): nullable ConnectionListener
        do
-               var listener = new ConnectionListener.bind_to(event_base, address.to_cstring, port, self)
+               var listener = new ConnectionListener.bind_tcp(
+                       event_base, address.to_cstring, port, self)
+
                if listener.address_is_null then
-                       sys.stderr.write "libevent warning: Opening {address}:{port} failed\n"
+                       print_error "libevent warning: Opening {address}:{port} failed, " +
+                               evutil_socket_error_to_string(evutil_socket_error).to_s
+                       return null
                end
+
                return listener
        end
 
-       # Put string representation of source `address` into `buf`
+       # Listen on a UNIX domain socket for new connections
+       #
+       # On new connections, libevent callbacks `spawn_connection`.
+       fun bind_unix(path: String): nullable ConnectionListener
+       do
+               # Delete the socket if it already exists
+               var stat = path.file_stat
+               if stat != null and stat.is_sock then path.file_delete
+
+               var listener = new ConnectionListener.bind_unix(
+                       event_base, path.to_cstring, self)
+
+               if listener.address_is_null then
+                       print_error "libevent warning: Opening UNIX domain socket {path} failed, " +
+                               evutil_socket_error_to_string(evutil_socket_error).to_s
+                       return null
+               end
+
+               return listener
+       end
+
+       # Put a human readable string representation of `address` into `buf`
        private fun addrin_to_address(address: Pointer, buf: CString, buf_len: Int): CString `{
                struct sockaddr *addrin = (struct sockaddr*)address;
 
@@ -512,6 +561,14 @@ class ConnectionFactory
                        struct in6_addr *src = &((struct sockaddr_in6*)addrin)->sin6_addr;
                        return (char *)inet_ntop(addrin->sa_family, src, buf, buf_len);
                }
+               else if (addrin->sa_family == AF_UNIX) {
+                       struct sockaddr_un *src = (struct sockaddr_un*)addrin;
+                       char *path = src->sun_path;
+                       if (path == NULL) return "Unnamed UNIX domain socket";
+                       if (path[0] == '\0') return "Abstract UNIX domain socket";
+                       return path;
+               }
+
                return NULL;
        `}
 end
diff --git a/lib/libevent/libevent_example.nit b/lib/libevent/libevent_example.nit
new file mode 100644 (file)
index 0000000..c00917e
--- /dev/null
@@ -0,0 +1,57 @@
+# 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.
+
+# Minimal usage example of libevent
+module libevent_example is example
+
+import libevent
+
+# Factory creating instances of `EchoConnection` to handle new connections
+class MyFactory
+       super ConnectionFactory
+
+       redef fun spawn_connection(buf, address)
+       do
+               return new EchoConnection(buf)
+       end
+end
+
+# Connection echoing data received from clients back at them
+class EchoConnection
+       super Connection
+
+       redef fun read_callback(content)
+       do
+               print "Received: {content}"
+               write content
+       end
+end
+
+# Skip the actual execution when testing
+if "NIT_TESTING".environ == "true" then exit 0
+
+# Setup libevent system
+var event_base = new NativeEventBase
+var factory = new MyFactory(event_base)
+
+# Open a TCP socket for listening
+factory.bind_tcp("localhost", 8888)
+
+# Open a UNIX domain socket for listening
+factory.bind_unix("/tmp/my.sck")
+
+# Launch event loop
+event_base.dispatch
+
+event_base.free
diff --git a/lib/libevent/libevent_test.nit b/lib/libevent/libevent_test.nit
new file mode 100644 (file)
index 0000000..4c64b2e
--- /dev/null
@@ -0,0 +1,94 @@
+# 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.
+
+module libevent_test
+
+import libevent
+import pthreads
+
+redef class Sys
+
+       var testing_id: Int is lazy do
+               var id = "NIT_TESTING_ID".environ
+               return if id.is_empty then 0 else id.to_i
+       end
+
+       # Config for test sockets
+       var tcp_addr = "localhost"
+       var tcp_port: Int = 20000 + testing_id
+       var unix_socket_path = "/tmp/libevent_test{testing_id}.sck"
+end
+
+class TestConnectionFactory
+       super ConnectionFactory
+
+       redef fun spawn_connection(buf, address)
+       do
+               print "[Server] New client: {address}"
+
+               var conn = new TestConnection(buf)
+               print "[Server] Write: Hi"
+               conn.write "Hi\n"
+               return conn
+       end
+end
+
+class TestConnection
+       super Connection
+
+       redef fun read_callback(content)
+       do
+               0.2.sleep # Forcing the server output after the client output
+               printn "[Server] Read: {content}"
+       end
+end
+
+class ServerThread
+       super Thread
+
+       redef fun main
+       do
+               var event_base = new NativeEventBase
+               var factory = new TestConnectionFactory(event_base)
+
+               # Bind TCP socket
+               factory.bind_tcp(tcp_addr, tcp_port)
+
+               # Bind UNIX domain socket
+               factory.bind_unix unix_socket_path
+
+               event_base.dispatch
+               event_base.free
+
+               return null
+       end
+end
+
+redef fun system(cmd)
+do
+       if testing_id == 0 then print "[Client] {cmd}"
+       return super(cmd)
+end
+
+# First, launch a server in the background
+var server = new ServerThread
+server.start
+0.1.sleep
+
+# Test what should succeed
+system "echo 'Hello TCP' | nc -N {tcp_addr} {tcp_port}"
+system "echo 'Hello UNIX' | nc -NU {unix_socket_path}"
+
+1.0.sleep
+exit 0
index c24d489..38f78e9 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name=libevent
-tags=wrapper,lib
+tags=network,wrapper,lib
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
 desc=Low-level wrapper around the libevent library to manage events on file descriptors
diff --git a/lib/markdown2/markdown2.nit b/lib/markdown2/markdown2.nit
new file mode 100644 (file)
index 0000000..85da1b9
--- /dev/null
@@ -0,0 +1,27 @@
+# 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.
+
+module markdown2
+
+import markdown_block_parsing
+import markdown_html_rendering
+
+redef class String
+       fun md_to_html2: String do
+               var parser = new MdParser
+               var doc = parser.parse(self)
+               var renderer = new HtmlRenderer
+               return renderer.render(doc)
+       end
+end
diff --git a/lib/markdown2/markdown_ast.nit b/lib/markdown2/markdown_ast.nit
new file mode 100644 (file)
index 0000000..3de2196
--- /dev/null
@@ -0,0 +1,487 @@
+# 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.
+
+# Markdown AST representation
+module markdown_ast
+
+# An abstract node
+abstract class MdNode
+
+       # Node location in original markdown
+       var location: MdLocation
+
+       # Node parent
+       var parent: nullable MdNode = null is writable
+
+       # First child
+       var first_child: nullable MdNode = null is writable
+
+       # Last child
+       var last_child: nullable MdNode = null is writable
+
+       # Previous node
+       var prev: nullable MdNode = null is writable
+
+       # Next node
+       var next: nullable MdNode = null is writable
+
+       # Children nodes of `self`
+       fun children: Array[MdNode] do
+               var nodes = new Array[MdNode]
+
+               var node = first_child
+               while node != null do
+                       nodes.add node
+                       node = node.next
+               end
+
+               return nodes
+       end
+
+       # Append a child to `self`
+       fun append_child(child: MdNode) do
+               child.unlink
+               child.parent = self
+               if last_child != null then
+                       last_child.as(not null).next = child
+                       child.prev = last_child
+                       last_child = child
+               else
+                       first_child = child
+                       last_child = child
+               end
+       end
+
+       # Prepend a child to `self`
+       fun prepend_child(child: MdNode) do
+               child.unlink
+               child.parent = self
+               if first_child != null then
+                       first_child.as(not null).prev = child
+                       child.next = first_child
+                       first_child = child
+               else
+                       first_child = child
+                       last_child = child
+               end
+       end
+
+       # Unlink `self` from its `parent`
+       fun unlink do
+               if prev != null then
+                       prev.as(not null).next = next
+               else if parent != null then
+                       parent.as(not null).first_child = next
+               end
+               if next != null then
+                       next.as(not null).prev = prev
+               else if parent != null then
+                       parent.as(not null).last_child = prev
+               end
+               parent = null
+               next = null
+               prev = null
+       end
+
+       # Insert `sibling` after `self`.
+       fun insert_after(sibling: MdNode) do
+               sibling.unlink
+               sibling.next = next
+               if sibling.next != null then
+                       sibling.next.as(not null).prev = sibling
+               end
+               sibling.prev = self
+               next = sibling
+               sibling.parent = parent
+               if sibling.next == null then
+                       sibling.parent.as(not null).last_child = sibling
+               end
+       end
+
+       # Insert `sibling` before `self`.
+       fun insert_before(sibling: MdNode) do
+               sibling.unlink
+               sibling.prev = prev
+               if sibling.prev != null then
+                       sibling.prev.as(not null).next = sibling
+               end
+               sibling.next = self
+               prev = sibling
+               sibling.parent = parent
+               if sibling.prev == null then
+                       sibling.parent.as(not null).first_child = sibling
+               end
+       end
+
+       # Visit all children or `self`
+       fun visit_all(v: MdVisitor) do
+               var node = first_child
+               while node != null do
+                       var next = node.next
+                       v.visit(node)
+                       node = next
+               end
+       end
+
+       redef fun to_s do return "{super}\{{to_s_attrs}\}"
+
+       # Returns `self` attributes as a String
+       #
+       # Mainly used for debug purposes.
+       fun to_s_attrs: String do return "loc: {location}"
+
+       # Print `self` AST
+       fun debug do
+               var v = new MdASTPrinter
+               v.enter_visit(self)
+       end
+end
+
+# A visitor for Markdown AST
+interface MdVisitor
+
+       # Start visiting `node`
+       fun enter_visit(node: MdNode) do visit(node)
+
+       # Visit `node`
+       #
+       # Method to define in specific visitor.
+       # It should not be called directly but used by `enter_visit`.
+       protected fun visit(node: MdNode) is abstract
+end
+
+# Print the AST content
+class MdASTPrinter
+       super MdVisitor
+
+       # Current indent level
+       var indent = 0
+
+       # Visit `self` to print the AST content
+       fun print_ast(node: MdNode) do
+               print "{"  " * indent}{node}"
+               indent += 1
+               node.visit_all(self)
+               indent -= 1
+       end
+
+       redef fun visit(node) do print_ast(node)
+end
+
+# Blocks
+
+# An abstract markdown block
+abstract class MdBlock
+       super MdNode
+
+       redef fun parent do return super
+
+       # Can this block contain other blocks?
+       var is_container = false
+
+       # Can this block contain `block`?
+       fun can_contain(block: MdBlock): Bool do return false
+
+       # Parents of blocks can only be blocks
+       redef fun parent=(node) do
+               assert parent == null or parent isa MdBlock else
+                       print "Parent of block must also be block."
+               end
+               super(node)
+       end
+end
+
+# A Markdown document
+class MdDocument
+       super MdBlock
+
+       redef var is_container = true
+
+       redef fun can_contain(block) do return true
+end
+
+# A block quote
+class MdBlockQuote
+       super MdBlock
+
+       redef var is_container = true
+
+       redef fun can_contain(block) do return true
+end
+
+# A block of code (indented or fenced)
+abstract class MdCodeBlock
+       super MdBlock
+
+       # Literal content
+       var literal: nullable String = null is writable
+
+       # Fence info / meta
+       var info: nullable String = null is writable
+
+       redef fun to_s_attrs do return "{super}, info={info or else "null"}, literal={literal or else "null"}"
+end
+
+# A block code that starts with an indent
+class MdIndentedCodeBlock
+       super MdCodeBlock
+
+       # Does this block use tabs instead of spaces?
+       var use_tabs: Bool
+
+       redef fun to_s_attrs do return "{super}, use_tabs={use_tabs}"
+end
+
+# A code block that starts with a fence
+class MdFencedCodeBlock
+       super MdCodeBlock
+
+       # Fence character
+       var fence_char: Char
+
+       # Fence length
+       var fence_length: Int
+
+       # Fence indentation level
+       var fence_indent: Int
+
+       redef fun to_s_attrs do return "{super}, fence_char={fence_char}, fence_length={fence_length}, fence_indent={fence_indent}"
+end
+
+# A heading
+class MdHeading
+       super MdBlock
+
+       # Heading level (from 1 to 6)
+       var level: Int
+
+       # Is this heading in the setext format in the original source?
+       var is_setext = false is optional
+
+       # Does this heading has an atx trailing in the original source?
+       var has_atx_trailing = false is optional
+
+       redef fun to_s_attrs do return "{super}, level={level}"
+end
+
+# An html block
+class MdHtmlBlock
+       super MdBlock
+
+       # Literal content
+       var literal: nullable String = null is writable
+
+       redef fun to_s_attrs do return "{super}, literal={literal or else "null"}"
+end
+
+# An ordered or unordered list block
+abstract class MdListBlock
+       super MdBlock
+
+       # Does this list contains line breaks?
+       var is_tight: Bool = false is writable
+
+       redef var is_container = true
+
+       redef fun can_contain(block) do return block isa MdListItem
+
+       redef fun to_s_attrs do return "{super}, is_tight={is_tight}"
+end
+
+# An ordered or unordered list item block
+class MdListItem
+       super MdBlock
+
+       redef var is_container = true
+
+       redef fun can_contain(block) do return true
+end
+
+# An ordered list block
+class MdOrderedList
+       super MdListBlock
+
+       # List starting number
+       var start_number: Int
+
+       # List number delimiter
+       var delimiter: Char
+
+       redef fun to_s_attrs do return "{super}, start_number={start_number}, delimiter={delimiter}"
+end
+
+# An unordered list
+class MdUnorderedList
+       super MdListBlock
+
+       # List bullet marker
+       var bullet_marker: Char
+
+       redef fun to_s_attrs do return "{super}, bullet_marker={bullet_marker}"
+end
+
+# A paragraph block
+class MdParagraph
+       super MdBlock
+
+       # Is this paragraph in a list?
+       fun is_in_list: Bool do
+               var parent = self.parent
+               return parent != null and parent.parent isa MdListBlock
+       end
+
+       # Is this paragraph in a tight list?
+       fun is_in_tight_list: Bool do
+               var parent = self.parent
+               if parent == null then return false
+               var gramps = parent.parent
+               return gramps isa MdListBlock and gramps.is_tight
+       end
+end
+
+# A ruler
+class MdThematicBreak
+       super MdBlock
+
+       # Thematic break pattern used in markdown source
+       var original_pattern: String
+end
+
+# Inline nodes
+
+# A line break (soft or hard)
+abstract class MdLineBreak
+       super MdNode
+end
+
+# A hardline break (`\\n` or `  \n`)
+class MdHardLineBreak
+       super MdLineBreak
+
+       # Does this line break used a backslash in the original source?
+       var has_backslash: Bool
+end
+
+# A soft line breack (`\r` or `\n`)
+class MdSoftLineBreak
+       super MdLineBreak
+end
+
+# An inline code string
+class MdCode
+       super MdNode
+
+       # Emphasis delimiter
+       var delimiter: String
+
+       # Literal content
+       var literal: String is writable
+
+       redef fun to_s_attrs do return "{super}, literal={literal}"
+end
+
+# A node that users delimiters in the Markdown form
+#
+# For example the emphasis: `*bold*`.
+abstract class MdDelimited
+       super MdNode
+
+       # Emphasis delimiter
+       var delimiter: String
+
+       # Opening delimiter
+       fun opening_delimiter: String do return delimiter
+
+       # Closing delimiter
+       fun closing_delimiter: String do return delimiter
+
+       redef fun to_s_attrs do return "{super}, delimiter={delimiter}"
+end
+
+# An emphasis
+class MdEmphasis
+       super MdDelimited
+end
+
+# A strong emphasis token
+class MdStrongEmphasis
+       super MdDelimited
+end
+
+# An inlined html string
+class MdHtmlInline
+       super MdNode
+
+       # Literal content
+       var literal: String is writable
+
+       redef fun to_s_attrs do return "{super}, literal={literal}"
+end
+
+# A link or image
+abstract class MdLinkOrImage
+       super MdNode
+
+       # Link destination
+       var destination: String is writable
+
+       # Link title
+       var title: nullable String is writable
+
+       # Is the `destination` between pointy brackets `<dest>`
+       var has_brackets = false is writable
+
+       redef fun to_s_attrs do return "{super}, destination={destination}, title={title or else "null"}"
+end
+
+# An image
+class MdImage
+       super MdLinkOrImage
+end
+
+# A link
+class MdLink
+       super MdLinkOrImage
+
+       # Is this link an autolink?
+       var is_autolink = false is optional, writable
+end
+
+# A raw text token
+class MdText
+       super MdNode
+
+       # Literal content
+       var literal: String is writable
+
+       redef fun to_s_attrs do return "{super}, literal={literal}"
+end
+
+# MdNode location in the Markdown input
+class MdLocation
+
+       # Starting line number (starting from 1).
+       var line_start: Int is writable
+
+       # Starting column number (starting from 1).
+       var column_start: Int is writable
+
+       # Stopping line number (starting from 1).
+       var line_end: Int is writable
+
+       # Stopping column number (starting from 1).
+       var column_end: Int is writable
+
+       redef fun to_s do return "{line_start},{column_start}--{line_end},{column_end}"
+end
diff --git a/lib/markdown2/markdown_block_parsing.nit b/lib/markdown2/markdown_block_parsing.nit
new file mode 100644 (file)
index 0000000..cfa07b5
--- /dev/null
@@ -0,0 +1,1503 @@
+# 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.
+
+# Markdown blocks parsing
+#
+# Introduce the parsers for the different Markdown blocks such as headings, lists
+# code blocks etc.
+module markdown_block_parsing
+
+import markdown_inline_parsing
+
+# Markdown parser
+#
+# Used to create the AST representation of a Markdown document.
+class MdParser
+
+       # Inline parser used to parse block content
+       private var inline_parser = new MdInlineParser is lazy
+
+       # Block parsers factories
+       private var block_parser_factories: Collection[MdBlockParserFactory] do
+               var factories = new Array[MdBlockParserFactory]
+               factories.add new MdBlockQuoteParserFactory
+               factories.add new MdHeadingParserFactory
+               factories.add new MdFencedCodeBlockParserFactory
+               factories.add new MdHtmlBlockParserFactory
+               factories.add new MdThematicBreakParserFactory
+               factories.add new MdListBlockParserFactory
+               factories.add new MdIndentedCodeBlockParserFactory
+               return factories
+       end
+
+       # Active block parsers
+       #
+       # Used as a stack to parse nested blocks.
+       private var active_block_parsers = new Array[MdBlockParser]
+
+       # All active block parsers
+       private var all_block_parsers = new HashSet[MdBlockParser]
+
+       # Return the active block parser
+       #
+       # The last entry in the `active_block_parsers` stack.
+       private fun active_block_parser: MdBlockParser do
+               return active_block_parsers.last
+       end
+
+       # Activate a `block_parser`
+       #
+       # Add the `block_parser` on the top of the `active_block_parsers` stack.
+       # Also register it in `all_block_parsers`.
+       private fun activate_block_parser(block_parser: MdBlockParser) do
+               active_block_parsers.add block_parser
+               all_block_parsers.add block_parser
+       end
+
+       # Deactivate the `active_block_parser`
+       private fun deactivate_block_parser do
+               active_block_parsers.pop
+       end
+
+       # Deactivate and remove the `active_block_parser` from the `all_block_parsers` list
+       private fun remove_active_block_parser do
+               var old = active_block_parser
+               deactivate_block_parser
+               all_block_parsers.remove(old)
+               old.block.unlink
+       end
+
+       # Post-processors applied after the parsing of a document
+       var post_processors = new Array[MdPostProcessor] is writable
+
+       # Currently parsed line
+       private var line_string: String is noinit
+
+       # Current index (offset) in input `line_string` (starts at 0)
+       private var index = 0
+
+       # Current column in input `line_string` (starts at 0)
+       #
+       # Tab causes column to go to next 4-space tab stop.
+       private var column = 0
+
+       # Is the current column within a tab character (partially consumed tab)
+       private var column_is_in_tab: Bool is noinit
+
+       # Current line in input string (starts at 1)
+       private var line = 1
+
+       # Index of the next non-space character starting from `index`
+       private var next_non_space_index = 0
+
+       # Next non-space column
+       private var next_non_space_column = 0
+
+       # Current indent in columns
+       #
+       # Either by spaces or tab stop of 4, starting from `column`.
+       private var indent = 0
+
+       # Is the current `line` blank starting from `index`?
+       private var is_blank: Bool is noinit
+
+       # Does a node end with a blank line?
+       private var last_line_blank = new HashMap[MdNode, Bool]
+
+       # Initialize parser state
+       private fun initialize do
+               active_block_parsers.clear
+               all_block_parsers.clear
+               index = 0
+               column = 0
+               column_is_in_tab = false
+               line = 1
+               next_non_space_index = 0
+               next_non_space_column = 0
+               indent = 0
+               is_blank = false
+               last_line_blank.clear
+       end
+
+       # Parse the `input` string as a MdDocument
+       fun parse(input: String): MdDocument do
+               initialize
+
+               var document_block_parser = new MdDocumentBlockParser(1, 1, 0)
+               activate_block_parser(document_block_parser)
+               var line_start = 0
+               var line_break = find_line_break(input, line_start)
+               while line_break != -1 do
+                       var line_string = input.substring(line_start, line_break - line_start)
+                       incorporate_line(line_string)
+                       if line_break + 1 < input.length and
+                          input.chars[line_break] == '\r' and
+                          input.chars[line_break + 1] == '\n' then
+                               line_start = line_break + 2
+                       else
+                               line_start = line_break + 1
+                       end
+                       line_break = find_line_break(input, line_start)
+                       line += 1
+                       column = 0
+               end
+
+               # Finalize pending line
+               if input.length > 0 and (line_start == 0 or line_start < input.length) then
+                       incorporate_line(input.substring(line_start, input.length - line_start))
+               end
+               finalize_blocks(active_block_parsers)
+
+               # Walk through a block and its chiildren revursively
+               # Parsing string content into inline content where appropriate.
+               var all_block_parsers = all_block_parsers.to_a
+               var i = all_block_parsers.length - 1
+               while i >= 0 do
+                       var block_parser = all_block_parsers[i]
+                       block_parser.parse_inlines(inline_parser)
+                       i -= 1
+               end
+               var document = document_block_parser.block
+               return document
+       end
+
+       # Post-process the `document`
+       fun post_process(document: MdDocument) do
+               for processor in post_processors do
+                       processor.post_process(self, document)
+               end
+       end
+
+       # Analyze a line of text and update the document
+       #
+       # We parse Markdown text by calling this on each line of `input`.
+       private fun incorporate_line(input: String) do
+               line_string = input
+               index = 0
+               column = 0
+               column_is_in_tab = false
+
+               # For each containing block, try to parse the associated line start.
+               var matches = 1
+               for i in [1 .. active_block_parsers.length[ do
+                       var block_parser = active_block_parsers[i]
+                       find_next_non_space
+
+                       var result = block_parser.try_continue(self)
+                       if result isa MdBlockContinue then
+                               if result.is_finalize then
+                                       block_parser.finalize(self)
+                                       return
+                               else
+                                       if result.new_index != -1 then
+                                               set_new_index result.new_index
+                                       else if result.new_column != -1 then
+                                               set_new_column result.new_column
+                                       end
+                               end
+                               matches += 1
+                       else
+                               break
+                       end
+               end
+
+               var unmatched_block_parsers = active_block_parsers.subarray(
+                       matches, active_block_parsers.length - matches)
+               var last_matched_block_parser = active_block_parsers[matches - 1]
+               var block_parser = last_matched_block_parser
+               var all_closed = unmatched_block_parsers.is_empty
+
+               # Unless last matched container is a code block, try new container starts,
+               # adding children to the last matched container.
+               var try_block_starts = block_parser.block isa MdParagraph or
+                       block_parser.block.is_container
+
+               while try_block_starts do
+                       find_next_non_space
+
+                       # Optimize lookup
+                       if is_blank or (indent < 4 and line_string.chars[next_non_space_index].is_letter) then
+                               set_new_index next_non_space_index
+                               break
+                       end
+
+                       var block_start = find_block_start(block_parser)
+                       if block_start == null then
+                               set_new_index next_non_space_index
+                               break
+                       end
+
+                       if not all_closed then
+                               finalize_blocks(unmatched_block_parsers)
+                               all_closed = true
+                       end
+
+                       if block_start.new_index != -1 then
+                               set_new_index block_start.new_index
+                       else if block_start.new_column != -1 then
+                               set_new_column block_start.new_column
+                       end
+
+                       if block_start.replace_active_block_parser then
+                               remove_active_block_parser
+                       end
+
+                       for new_block_parser in block_start.block_parsers do
+                               add_child(new_block_parser)
+                               block_parser = new_block_parser
+                               try_block_starts = new_block_parser.block.is_container
+                       end
+               end
+
+               # What remains at the offset is a text line.
+               # Add the text to the appropriate block.
+
+               # First check for a lazy paragraph continuation
+               if not all_closed and not is_blank and active_block_parser isa MdParagraphParser then
+                       add_line
+               else
+                       # Finalize any blocks not matched
+                       if not all_closed then
+                               finalize_blocks(unmatched_block_parsers)
+                       end
+                       propagate_last_line_blank(block_parser, last_matched_block_parser)
+
+                       if not block_parser.block.is_container then
+                               add_line
+                       else if not is_blank then
+                               # Create a paragraph container for the line
+                               add_child(new MdParagraphParser(line, column + 1, block_parser.content_offset))
+                               add_line
+                       end
+               end
+       end
+
+       # Find what kind of block starts at `index` in `input`
+       private fun find_block_start(block_parser: MdBlockParser): nullable MdBlockStart do
+               for block_parser_factory in block_parser_factories do
+                       var result = block_parser_factory.try_start(self, block_parser)
+                       if result != null then return result
+               end
+               return null
+       end
+
+       # Add a `block_parser` block's as child of the active block parser block
+       private fun add_child(block_parser: MdBlockParser) do
+               # Finalize non-parentable blocks
+               while not active_block_parser.block.can_contain(block_parser.block) do
+                       active_block_parser.finalize(self)
+               end
+               # Append block block parser block to its parent
+               active_block_parser.block.append_child(block_parser.block)
+               activate_block_parser(block_parser)
+       end
+
+       # Add line content to the active block parser
+       #
+       # We assume it can accept lines.
+       private fun add_line do
+               var content = null
+               if column_is_in_tab then
+                       # Out column is in a partially consumed tab.
+                       # Expand the remaining columns to the next tab stop to spaces.
+                       var after_tab = index + 1
+                       var rest = line_string.substring(after_tab, line_string.length - after_tab)
+                       var spaces = column.columns_to_next_tab_stop
+                       var buffer = new Buffer
+                       for i in [0 .. spaces[ do
+                               buffer.add ' '
+                       end
+                       buffer.append(rest)
+                       content = buffer.write_to_string
+               else
+                       content = line_string.substring(index, line_string.length - index)
+               end
+               active_block_parser.add_line(content)
+       end
+
+       # Finalize blocks of previous line
+       private fun finalize_blocks(block_parsers: Sequence[MdBlockParser]) do
+               var i = block_parsers.length - 1
+               while i >= 0 do
+                       var block_parser = block_parsers[i]
+                       block_parser.finalize(self)
+                       i -= 1
+               end
+       end
+
+       # Advance the `index` position to the next character
+       #
+       # Also set the `column`.
+       # If the next character is a tab, compute the new column accordingly.
+       private fun advance do
+               var c = line_string.chars[index]
+               if c == '\t' then
+                       index += 1
+                       column += column.columns_to_next_tab_stop
+               else
+                       index += 1
+                       column += 1
+               end
+       end
+
+       # Move `index` to the next non-space character index in the `input` string
+       #
+       # Also set `next_non_space_index`, `next_non_space_column`, `is_blank` and `indent`.
+       private fun find_next_non_space do
+               var i = index
+               var cols = column
+
+               is_blank = true
+               while i < line_string.length do
+                       var c = line_string.chars[i]
+                       if c == ' ' then
+                               i += 1
+                               cols += 1
+                               continue
+                       else if c == '\t' then
+                               i += 1
+                               cols += 4 - (cols % 4)
+                               continue
+                       end
+                       is_blank = false
+                       break
+               end
+
+               next_non_space_index = i
+               next_non_space_column = cols
+               indent = next_non_space_column - column
+       end
+
+       # Return the position of the next line break
+       #
+       # We consider `\r` and `\n`.
+       private fun find_line_break(input: String, start_index: Int): Int do
+               for i in [start_index .. input.length[ do
+                       var char = input.chars[i]
+                       if char == '\r' or char == '\n' then return i
+               end
+               return -1
+       end
+
+       # Set the parser `index` at `new_index`
+       #
+       # Also set `column` and `column_is_in_tab`.
+       private fun set_new_index(new_index: Int) do
+               if new_index >= next_non_space_index then
+                       # We can start from here, no need to calculate tab stops again
+                       index = next_non_space_index
+                       column = next_non_space_column
+               end
+               while index < new_index and index != line_string.length do
+                       advance
+               end
+               # If we're going to an index as opposed to a column, we're never within a tab
+               column_is_in_tab = false
+       end
+
+       # Set the parser `column` at `new_column`
+       #
+       # Also set `index` and `column_is_in_tab`.
+       private fun set_new_column(new_column: Int) do
+               if new_column >= next_non_space_column then
+                       # We can start from here, no need to calculate tab stops again
+                       index = next_non_space_index
+                       column = next_non_space_column
+               end
+               while column < new_column and index != line_string.length do
+                       advance
+               end
+               if column > new_column then
+                       # Last character was a tab and we overshot our target
+                       index -= 1
+                       column = new_column
+                       column_is_in_tab = true
+               else
+                       column_is_in_tab = false
+               end
+       end
+
+       # Does `block` end with a blank line?
+       private fun ends_with_blank_line(block: nullable MdNode): Bool do
+               while block != null do
+                       if is_last_line_blank(block) then return true
+                       if block isa MdListBlock or block isa MdListItem then
+                               block = block.last_child
+                       else
+                               break
+                       end
+               end
+               return false
+       end
+
+       # Propagate a blank line to all block_parser blocl's parents
+       private fun propagate_last_line_blank(block_parser: MdBlockParser, last_matched_block_parser: MdBlockParser) do
+               var last_child = block_parser.block.last_child
+               if is_blank and last_child != null then
+                       last_line_blank[last_child] = true
+               end
+               var block = block_parser.block
+
+               # Block quotes lines are never blank as they start with `>`.
+               # We don't count blanks in fenced code for purposes of thight/loose lists.
+               # We also don't set `last_line_blank` on an empty list item.
+               var last_line_blank = is_blank and
+                       not (block isa MdBlockQuote or
+                            block isa MdFencedCodeBlock or
+                                (block isa MdListItem and block.first_child == null and
+                                                                                 block_parser != last_matched_block_parser))
+
+               # Propagate `last_line_blank` up through parents
+               var node: nullable MdNode = block_parser.block
+               while node != null do
+                       self.last_line_blank[node] = last_line_blank
+                       node = node.parent
+               end
+       end
+
+       # Is last line blank for `node`?
+       private fun is_last_line_blank(node: MdNode): Bool do
+               if not last_line_blank.has_key(node) then return false
+               return last_line_blank[node]
+       end
+end
+
+# Block parsing
+
+# Parser for a specific block node
+abstract class MdBlockParser
+
+       # Kind of block under construction
+       type BLOCK: MdBlock
+
+       # MdBlock under construction
+       fun block: BLOCK is abstract
+
+       # Line Start
+       var line_start: Int
+
+       # Column start
+       var column_start: Int
+
+       # Location at start
+       #
+       # The location end it initialized at `-1` and will be set later in the
+       # `finalize` method.
+       var location: MdLocation is lazy do return new MdLocation(line_start, column_start, -1, -1)
+
+       # Column where the content starts
+       var content_offset: Int
+
+       # Initialize the current `block`
+       fun initialize(parser: MdParser) do end
+
+       # Can `self` continue from the current `index` in `parser`?
+       #
+       # Return a new `MdBlockContinue` if `self` can continue parsing.
+       # Return null otherwise.
+       fun try_continue(state: MdParser): nullable MdBlockContinue is abstract
+
+       # Add `line` to the current `block`
+       fun add_line(line: String) do end
+
+       # Finalize the current `block`
+       #
+       # Deactivate `self` from `parser` and call `close_block`.
+       fun finalize(parser: MdParser) do
+               if parser.active_block_parser == self then
+                       parser.deactivate_block_parser
+               end
+       end
+
+       # Parse `block` lines
+       fun parse_inlines(inline_parser: MdInlineParser) do end
+end
+
+# Result object for continuing parsing of a block
+class MdBlockContinue
+
+       # Index from which continue parsing
+       var new_index: Int
+
+       # Column from which continue parsing
+       var new_column: Int
+
+       # Is the block finalized?
+       var is_finalize: Bool
+
+       # Continue from index
+       init at_index(new_index: Int) do
+               init(new_index, -1, false)
+       end
+
+       # Continue from column
+       init at_column(new_column: Int) do
+               init(-1, new_column, false)
+       end
+
+       # Block is finished
+       init finished do
+               init(-1, -1, true)
+       end
+end
+
+# Block parser factory for a block node for determining when a block starts
+abstract class MdBlockParserFactory
+
+       # Can the associated block parser can start at the current line in `parser`?
+       #
+       # Return a new `MdBlockStart` if the block parser can start.
+       # Return null otherwise.
+       fun try_start(parser: MdParser, matched_block_parser: MdBlockParser):
+               nullable MdBlockStart is abstract
+end
+
+# Result object from starting parsing of a block
+class MdBlockStart
+
+       # Block parsers for this block start
+       var block_parsers: Array[MdBlockParser]
+
+       # Index where the parsing should start
+       var new_index = -1
+
+       # Column where the parsing should start
+       var new_column = -1
+
+       # Does the block starting with `self` terminate a previous block?
+       var replace_active_block_parser = false
+
+       # Start from `new_index`
+       fun at_index(new_index: Int): MdBlockStart do
+               self.new_index = new_index
+               return self
+       end
+
+       # Start from `new_column`
+       fun at_column(new_column: Int): MdBlockStart do
+               self.new_column = new_column
+               return self
+       end
+
+       # Start replacing the active block parser
+       fun replacing_active_block_parser: MdBlockStart do
+               self.replace_active_block_parser = true
+               return self
+       end
+end
+
+# Parser for the whole document
+class MdDocumentBlockParser
+       super MdBlockParser
+
+       redef type BLOCK: MdDocument
+       redef var block = new MdDocument(location) is lazy
+
+       # Always continue at current indent
+       redef fun try_continue(state) do return new MdBlockContinue.at_index(state.index)
+
+       redef fun finalize(parser) do
+       end
+
+       # redef fun finalize(state) do
+       redef fun parse_inlines(inline_parser) do
+               var last_child = block.last_child
+               if last_child != null then
+                       location.line_end = last_child.location.line_end
+                       location.column_end = last_child.location.column_end
+               end
+       end
+end
+
+# Headings parser
+class MdHeadingParser
+       super MdBlockParser
+
+       redef type BLOCK: MdHeading
+
+       redef var block = new MdHeading(location, level, is_setext, has_atx_trailing) is lazy
+
+       redef var location = new MdLocation(line_start, column_start, line_end, column_end) is lazy
+
+       # Line end
+       var line_end: Int
+
+       # Column end
+       var column_end: Int
+
+       # Heading level
+       var level: Int
+
+       # Heading content
+       var content: String
+
+       # Heading has ATX trailing
+       var has_atx_trailing: Bool
+
+       # Heading is setext format
+       var is_setext: Bool
+
+       # Never continue parsing as an heading is a one liner
+       redef fun try_continue(state) do return null
+
+       # Parse the heading content
+       redef fun parse_inlines(inline_parser) do
+               inline_parser.parse(content, content_offset, block)
+       end
+end
+
+# Heading parser factory
+class MdHeadingParserFactory
+       super MdBlockParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               if state.indent >= 4 then return null
+
+               var next_non_space = state.next_non_space_index
+               var line = state.line_string
+               var paragraph = null
+               if matched_block_parser isa MdParagraphParser then
+                       paragraph = matched_block_parser.content
+               end
+
+               var line_content = line.substring(next_non_space, line.length - next_non_space)
+               var match = line_content.search(re_atx_heading)
+               if match != null then
+                       # ATX heading
+                       var new_offset = next_non_space + match.subs.first.as(not null).length
+                       var level = match.subs.first.as(not null).to_s.trim.length
+                       # remove trailing ###s
+                       var after_leading = line.substring(new_offset, line.length - new_offset)
+                       var trailing = after_leading.search(re_atx_trailing)
+                       var has_trailing = trailing != null
+                       var trailing_length = if trailing != null then trailing.length else 0
+                       var content = after_leading.replace(re_atx_trailing, "")
+                       return (new MdBlockStart(
+                               [new MdHeadingParser(
+                                       state.line,
+                                       next_non_space + 1,
+                                       new_offset + 1,
+                                       state.line,
+                                       new_offset + content.length + trailing_length,
+                                       level,
+                                       content,
+                                       has_trailing, false)])
+                               ).at_index(line.length)
+               end
+
+               if paragraph ==  null then return null
+
+               match = line_content.search(re_setext_heading)
+               if match == null then return null
+               var level = 2
+               if match.subs.first.as(not null).to_s.chars.first == '=' then level = 1
+               var content = paragraph.to_s
+               return (new MdBlockStart(
+                       [new MdHeadingParser(
+                               state.line - 1,
+                               next_non_space + 1,
+                               0,
+                               state.line,
+                               state.column + match.length,
+                               level,
+                               content,
+                               false, true)])
+                       ).at_index(line.length).replacing_active_block_parser
+       end
+end
+
+# Blockquotes parser
+class MdBlockQuoteParser
+       super MdBlockParser
+
+       redef type BLOCK: MdBlockQuote
+       redef var block = new MdBlockQuote(location) is lazy
+
+       redef fun try_continue(state) do
+               var next_non_space = state.next_non_space_index
+               var indent = state.indent
+               var line = state.line_string
+
+               if indent >= 4 then return null
+               if next_non_space >= line.length then return null
+               if line.chars[next_non_space] != '>' then return null
+
+               var new_column = state.column + state.indent + 1
+               # optional following space or tab
+               if state.line_string.is_space_or_tab(next_non_space + 1) then
+                       new_column += 1
+               end
+               return new MdBlockContinue.at_column(new_column)
+       end
+
+       redef fun parse_inlines(inline_parser) do
+               var last_child = block.last_child
+               if last_child != null then
+                       location.line_end = last_child.location.line_end
+                       location.column_end = last_child.location.column_end
+               end
+       end
+end
+
+# Blockquotes parser factory
+class MdBlockQuoteParserFactory
+       super MdBlockParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               var next_non_space = state.next_non_space_index
+               var indent = state.indent
+               var line = state.line_string
+
+               if indent >= 4 then return null
+               if next_non_space >= line.length then return null
+               if line.chars[next_non_space] != '>' then return null
+
+               var new_column = state.column + state.indent + 1
+               # optional following space or tab
+               if state.line_string.is_space_or_tab(next_non_space + 1) then
+                       new_column += 1
+               end
+               return (new MdBlockStart(
+                       [new MdBlockQuoteParser(
+                               state.line,
+                               state.column + 1,
+                               new_column)])
+                       ).at_column(new_column)
+       end
+end
+
+# Indented code blocks parser
+class MdIndentedCodeBlockParser
+       super MdBlockParser
+
+       redef type BLOCK: MdIndentedCodeBlock
+       redef var block = new MdIndentedCodeBlock(location, use_tabs) is lazy
+
+       # Indent is tab?
+       var use_tabs: Bool
+
+       # Block content
+       var content = new Buffer
+
+       redef fun try_continue(state) do
+               if state.indent >= 4 then
+                       return new MdBlockContinue.at_column(state.column + 4)
+               else if state.is_blank then
+                       return new MdBlockContinue.at_index(state.next_non_space_index)
+               end
+               return null
+       end
+
+       redef fun add_line(line) do
+               if not content.is_empty then
+                       content.add('\n')
+               end
+               content.append(line)
+       end
+
+       redef fun finalize(parser) do
+               super
+
+               add_line(" ")
+               var content = self.content.to_s
+               var literal = content.replace_first(re_trailing_blank_lines, "\n")
+               block.literal = literal
+
+               var lines = literal.split("\n")
+               location.line_end = location.line_start + lines.length - 2
+               location.column_end = content_offset + lines[lines.length - 2].length + 4
+       end
+end
+
+# Indented code blocks parser factory
+class MdIndentedCodeBlockParserFactory
+       super MdBlockParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               if state.indent < 4 then return null
+               if state.is_blank then return null
+               if state.active_block_parser.block isa MdParagraph then return null
+
+               var use_tabs = state.line_string.has_prefix("\t")
+               return (new MdBlockStart(
+                       [new MdIndentedCodeBlockParser(
+                               state.line,
+                               state.column + 1,
+                               state.column,
+                               use_tabs)])
+                       ).at_column(state.column + 4)
+       end
+end
+
+# Fenced code blocks parser
+class MdFencedCodeBlockParser
+       super MdBlockParser
+
+       redef type BLOCK: MdFencedCodeBlock
+       redef var block = new MdFencedCodeBlock(location, fence_char, fence_length, fence_indent) is lazy
+
+       # Fence character
+       var fence_char: Char
+
+       # Fence length
+       var fence_length: Int
+
+       # Fence indent
+       var fence_indent: Int
+
+       # Fence first line
+       var first_line: nullable String = null
+
+       # Fence other lines
+       var other_lines = new Buffer
+
+       redef fun try_continue(state) do
+               var next_non_space = state.next_non_space_index
+               var new_index = state.index
+               var line = state.line_string
+
+               if state.indent <= 3 and next_non_space < line.length and
+                  line.chars[next_non_space] == fence_char then
+
+                       var match = line.substring(next_non_space, line.length - next_non_space).
+                               search(re_closing_fence)
+                       if match != null and match.subs[0].as(not null).length >= fence_length then
+                               # closing fence - we're at end of line, so we can finalize now
+                               return new MdBlockContinue.finished
+                       end
+               end
+
+               # skip optional spaces of fence indent
+               var i = fence_indent
+               while i > 0 and new_index < line.length and line.chars[new_index] == ' ' do
+                       new_index += 1
+                       i -= 1
+               end
+
+               return new MdBlockContinue.at_index(new_index)
+       end
+
+       redef fun add_line(line) do
+               if first_line == null then
+                       first_line = line
+               else
+                       other_lines.append(line)
+                       other_lines.add '\n'
+               end
+       end
+
+       redef fun finalize(parser) do
+               super
+
+               # first line become info string
+               var first_line = self.first_line
+               if first_line != null then
+                       var info = first_line.trim.unescape_string
+                       if not info.is_empty then block.info = info
+               end
+
+               var content = other_lines.to_s
+               block.literal =  content
+
+               var lines = content.split("\n")
+               location.line_end = location.line_start + lines.length
+               location.column_end = content_offset + fence_indent + fence_length
+       end
+end
+
+# Fenced code blocks parser factory
+class MdFencedCodeBlockParserFactory
+       super MdBlockQuoteParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               var next_non_space = state.next_non_space_index
+               var line = state.line_string
+
+               if state.indent >= 4 then return null
+
+               var match = line.substring(next_non_space, line.length - next_non_space).search(re_opening_fence)
+               if match == null then return null
+
+               var fence_length
+               var fence_char
+               var sub0 = match.subs[0]
+               if sub0 != null then
+                       fence_length = sub0.length
+                       fence_char = sub0.to_s.chars.first
+               else
+                       fence_length = match.subs[2].as(not null).length
+                       fence_char = match.subs[2].as(not null).to_s.chars.first
+               end
+               if fence_char == '`' and match.to_s.has("[^`]+`".to_re) then
+                       return null
+               else if match.to_s.has("[^~]+~".to_re) then
+                       return null
+               end
+               return (new MdBlockStart(
+                       [new MdFencedCodeBlockParser(
+                               state.line,
+                               state.column + 1,
+                               state.column,
+                               fence_char,
+                               fence_length,
+                               state.indent)]
+                       )).at_index(next_non_space + fence_length)
+       end
+end
+
+# List blocks parser
+class MdListBlockParser
+       super MdBlockParser
+
+       redef type BLOCK: MdListBlock
+
+       redef var block is lazy do
+               if is_ordered then
+                       return new MdOrderedList(location, digit.as(not null), delim.as(not null))
+               else
+                       return new MdUnorderedList(location, bullet.as(not null))
+               end
+       end
+
+       # Is this list ordered
+       var is_ordered: Bool
+
+       # List bullet if unordered
+       var bullet: nullable Char
+
+       # List digit if ordered
+       var digit: nullable Int
+
+       # List delimiter if ordered
+       var delim: nullable Char
+
+       redef fun try_continue(state) do return new MdBlockContinue.at_index(state.index)
+
+       redef fun finalize(parser) do
+               super
+
+               var item = block.first_child
+               while item != null do
+                       # check for non-final list item ending with blank line
+                       if parser.ends_with_blank_line(item) and item.next != null then
+                               block.is_tight = false
+                               break
+                       end
+                       # recurse into children of list item to see if there are spaces between any of them
+                       var sub_item = item.first_child
+                       while sub_item != null do
+                               if parser.ends_with_blank_line(sub_item) and
+                                  (item.next != null or sub_item.next != null) then
+                                       block.is_tight = false
+                                       break
+                               end
+                               sub_item = sub_item.next
+                       end
+                       item = item.next
+               end
+       end
+
+       redef fun parse_inlines(inline_parser) do
+               var last_child = block.last_child
+               if last_child != null then
+                       location.line_end = last_child.location.line_end
+                       location.column_end = last_child.location.column_end
+               end
+       end
+end
+
+# List blocks parser factory
+class MdListBlockParserFactory
+       super MdBlockQuoteParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               if state.indent >= 4 and not matched_block_parser isa MdListBlockParser then return null
+
+               var marker_index = state.next_non_space_index
+               var marker_column = state.column + state.indent
+
+               var in_paragraph = matched_block_parser isa MdParagraphParser and matched_block_parser.content != null
+               var list_data = parse_list_marker(state, state.line_string, marker_index, marker_column, in_paragraph)
+               if list_data == null then return null
+
+
+               var new_column = list_data.content_column
+               var list_item_parser = new MdListItemParser(
+                       state.line,
+                       state.column + 1,
+                       new_column,
+                       new_column - state.column)
+
+               # prepend the list block if needed
+               if not matched_block_parser isa MdListBlockParser or not lists_match(matched_block_parser.block, list_data) then
+                       var list_block_parser = new MdListBlockParser(state.line, state.column + 1, new_column - state.column, list_data.is_ordered, list_data.bullet, list_data.digit, list_data.delim)
+                       list_block_parser.block.is_tight = true
+
+                       return (new MdBlockStart([list_block_parser, list_item_parser: MdBlockParser])).at_column(new_column)
+               end
+               return (new MdBlockStart([list_item_parser])).at_column(new_column)
+       end
+
+       private fun parse_list_marker(state: MdParser, line: String, marker_index, marker_column: Int, in_paragraph: Bool): nullable MdListData do
+               var rest = line.substring(marker_index, line.length - marker_index)
+               var match = rest.search(re_list_marker)
+               if match == null then return null
+
+               var is_ordered
+               var bullet = null
+               var digit = null
+               var delim = null
+
+               var bullet_match = match.subs[0]
+               if bullet_match != null then
+                       is_ordered = false
+                       bullet = bullet_match.to_s.chars[0]
+               else
+                       is_ordered = true
+                       digit = match.subs[2].as(not null).to_s.to_i
+                       delim = match.subs[3].as(not null).to_s.chars[0]
+               end
+
+               var marker_length = match.length
+               if match.to_s.has_suffix(" ") or match.to_s.has_suffix("\t") then
+                       marker_length -= 1
+               end
+               var index_after_marker = marker_index + marker_length
+
+               # marker doesn't include tabs, so counting them as column directly is ok
+               var column_after_marker = marker_column + marker_length
+               # the column within the line where the content starts
+               var content_column = column_after_marker
+
+               # see at which column the content starts if there is content
+               var has_content = false
+               for i in [index_after_marker .. line.length[ do
+                       var c = line.chars[i]
+                       if c == '\t' then
+                               content_column += content_column.columns_to_next_tab_stop
+                       else if c == ' ' then
+                               content_column += 1
+                       else
+                               has_content = true
+                               break
+                       end
+               end
+
+               if in_paragraph then
+                       # if the list item is ordered, then start number must be 1 to interrupt a paragraph
+                       if is_ordered and digit != 1 then
+                               return null
+                       end
+                       # empty list item can not interrupt a paragraph
+                       if not has_content then
+                               return null
+                       end
+               end
+
+               if not has_content or (content_column - column_after_marker) > 4 then
+                       # if this line is blank or has a code block, default to 1 space after marker
+                       content_column = column_after_marker + 1
+               end
+               return new MdListData(is_ordered, bullet, digit, delim, content_column)
+       end
+
+       # Return true if the two list items are of the same type
+       #
+       # With the same delimiter and bullet character.
+       # This is used in agglomerating list items into lists
+       private fun lists_match(a: MdListBlock, b: MdListData): Bool do
+               if a isa MdUnorderedList and not b.is_ordered then
+                       return a.bullet_marker == b.bullet
+               else if a isa MdOrderedList and b.is_ordered then
+                       return a.delimiter == b.delim
+               end
+               return false
+       end
+end
+
+# Parsed list data
+private class MdListData
+
+       var is_ordered: Bool
+
+       var bullet: nullable Char
+
+       var digit: nullable Int
+
+       var delim: nullable Char
+
+       # Column the content start at
+       var content_column: Int
+end
+
+# List items parser
+class MdListItemParser
+       super MdBlockParser
+
+       redef type BLOCK: MdListItem
+       redef var block = new MdListItem(location) is lazy
+
+       # List item content indend
+       var content_indent: Int
+
+       redef fun try_continue(state) do
+               if state.is_blank then
+                       if block.first_child == null then
+                               # blank line after empty list item
+                               return null
+                       end
+                       return new MdBlockContinue.at_index(state.next_non_space_index)
+               end
+               if state.indent >= content_indent then
+                       return new MdBlockContinue.at_column(state.column + content_indent)
+               end
+               return null
+       end
+
+       redef fun parse_inlines(inline_parser) do
+               var last_child = block.last_child
+               if last_child != null then
+                       location.line_end = last_child.location.line_end
+                       location.column_end = last_child.location.column_end
+               end
+       end
+end
+
+# Thematic breaks parser
+class MdThematicBreakParser
+       super MdBlockParser
+
+       redef type BLOCK: MdThematicBreak
+       redef var block = new MdThematicBreak(location, pattern) is lazy
+
+       # Thematic break pattern
+       var pattern: String
+
+       redef fun try_continue(state) do return null
+
+       redef fun finalize(parser) do
+               super
+
+               location.line_end = line_start
+               location.column_end = column_start + pattern.length - 1
+       end
+end
+
+# Thematic breaks parser factory
+class MdThematicBreakParserFactory
+       super MdBlockQuoteParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               if state.indent >= 4 then return null
+
+               var next_non_space = state.next_non_space_index
+               var line = state.line_string
+               var tbreak  = line.substring(next_non_space, line.length - next_non_space).search(re_thematic_break)
+               if tbreak != null then
+                       return (new MdBlockStart(
+                               [new MdThematicBreakParser(
+                                       state.line,
+                                       state.column + 1,
+                                       next_non_space,
+                                       tbreak.to_s)]
+                               )).at_index(line.length)
+               end
+               return null
+       end
+end
+
+# Paragraphs parser
+class MdParagraphParser
+       super MdBlockParser
+
+       redef type BLOCK: MdParagraph
+
+       redef var block = new MdParagraph(location) is lazy
+
+       # Paragraph content
+       var content: nullable Buffer = new Buffer
+
+       redef fun try_continue(state) do
+               if state.is_blank then return null
+               return new MdBlockContinue.at_index(state.index)
+       end
+
+       redef fun add_line(line) do
+               var content = self.content
+               if content == null then return
+               if not content.is_empty then
+                       content.add('\n')
+               end
+               content.append(line)
+       end
+
+       redef fun finalize(parser) do
+               super
+
+               var inline_parser = parser.inline_parser
+               var content = self.content
+               if content == null then return
+
+               var content_string = content.to_s
+               var has_reference_defs = false
+
+               var pos = inline_parser.parse_reference(content_string)
+               # try parsing the beginning as link reference definitions
+               while content_string.length > 3 and content_string.chars[0] == '[' and pos != 0 do
+                       content_string = content_string.substring(pos, content_string.length - pos)
+                       has_reference_defs = true
+                       pos = inline_parser.parse_reference(content_string)
+               end
+
+               if has_reference_defs and content_string.is_blank then
+                       block.unlink
+                       self.content = null
+               else
+                       self.content = new Buffer.from_text(content_string)
+               end
+       end
+
+       redef fun parse_inlines(inline_parser) do
+               var content = self.content
+               if content == null then return
+               inline_parser.parse(content.to_s, content_offset, block)
+
+               var last_child = block.last_child
+               if last_child != null then
+                       location.line_end = last_child.location.line_end
+                       location.column_end = last_child.location.column_end
+               end
+       end
+end
+
+# Html blocks parser
+class MdHtmlBlockParser
+       super MdBlockParser
+
+       redef type BLOCK: MdHtmlBlock
+       redef var block = new MdHtmlBlock(location) is lazy
+
+       # Closing tag pattern
+       #
+       # Or null if the block is not closed
+       var closing_pattern: nullable Pattern
+
+       # Is the current block finished?
+       var finished = false
+
+       # Block content
+       var content = new Buffer
+
+       redef fun try_continue(state) do
+               if finished then return null
+
+               # blank lin ends type 6 and 7 blocks
+               if state.is_blank and closing_pattern == null then return null
+
+               return new MdBlockContinue.at_index(state.index)
+       end
+
+       redef fun add_line(line) do
+               if not content.is_empty then
+                       content.add('\n')
+               end
+               content.append(line)
+               var closing_pattern = self.closing_pattern
+               if closing_pattern != null and line.has(closing_pattern) then
+                       finished = true
+               end
+       end
+
+       redef fun finalize(parser) do
+               super
+
+               var content = self.content.to_s
+               block.literal = content
+
+               var lines = content.split("\n")
+               location.line_end = location.line_start + lines.length - 1
+               location.column_end = lines.last.length
+       end
+end
+
+# Html blocks parser factory
+class MdHtmlBlockParserFactory
+       super MdBlockParserFactory
+
+       redef fun try_start(state, matched_block_parser) do
+               var next_non_space = state.next_non_space_index
+               var line = state.line_string
+
+               if state.indent >= 4 or line.chars[next_non_space] != '<' then return null
+
+               for block_type in [0..6] do
+                       # type 7 can not interrupt a paragraph
+                       if block_type == 6 and matched_block_parser.block isa MdParagraph then continue
+                       var opener = re_html_blocks[block_type].first
+                       var closer = re_html_blocks[block_type].last
+                       if line.substring(next_non_space, line.length - next_non_space).has(opener.as(not null)) then
+                               return (new MdBlockStart(
+                                       [new MdHtmlBlockParser(
+                                               state.line,
+                                               state.column + 1,
+                                               next_non_space,
+                                               closer)])
+                                       ).at_index(state.index)
+                       end
+               end
+               return null
+       end
+end
+
+# Post Processing
+
+# Markdown post processor
+#
+# A Markdown AST visitor called after parsing from a MdParser
+abstract class MdPostProcessor
+       super MdVisitor
+
+       # Document behing processed
+       #
+       # Availlable only during a call to `post_process`.
+       var document: nullable MdDocument = null
+
+       # Post process the `document` parsed by `parser`
+       fun post_process(parser: MdParser, document: MdDocument) do
+               self.document = document
+               enter_visit(document)
+               self.document = null
+       end
+
+       # Call `MdNode::post_process`
+       redef fun visit(node) do node.post_process(self)
+end
+
+redef class MdNode
+
+       # Accept the visit of a `MdPostProcessor`
+       fun post_process(v: MdPostProcessor) do visit_all(v)
+end
+
+# Utils
+
+redef class Sys
+       # ATX headings matching
+       private var re_atx_heading: Regex = "^(#\{1,6\})([ \t]+|$)".to_re
+
+       # ATX trailings matching
+       private var re_atx_trailing: Regex = "(^|[ \t]+)#+[ \t]*$".to_re
+
+       # SeText headings matching
+       private var re_setext_heading: Regex = "^(=+|-+)[ \t]*$".to_re
+
+       # Blank lines matching
+       var re_trailing_blank_lines: Regex = "(\n[ \t]*)+$".to_re
+
+       # Opening fence matching
+       var re_opening_fence: Regex = "^(`\{3,\})(.*)|^(~\{3,\})(.*)".to_re
+
+       # Closing fence matching
+       var re_closing_fence: Regex = "^(`\{3,\}|~\{3,\})( *$)".to_re
+
+       # List marker matching
+       var re_list_marker: Regex = "^([*+-])( |\t|$)|^([0-9]\{1,9\})([.)])( |\t|$)".to_re
+
+       # Thematic break pattern
+       var re_thematic_break: Regex = "^((\\*[ \t]*)\{3,\}|(_[ \t]*)\{3,\}|(-[ \t]*)\{3,\})[ \t]*$".to_re
+
+       # HTML blocks patterns
+       var re_html_blocks: Array[Array[nullable Regex]] do
+               var blocks = new Array[Array[nullable Regex]]
+
+               var re0_opening = "^<(script|pre|style)(\\s|>|$)".to_re
+               re0_opening.ignore_case = true
+               var re0_closing = "</(script|pre|style)>".to_re
+               re0_closing.ignore_case = true
+               blocks.add([re0_opening, re0_closing])
+
+               blocks.add([
+                       "^<!--".to_re,
+                       "-->".to_re
+               ])
+
+               blocks.add([
+                       "^<[?]".to_re,
+                       "\\?>".to_re
+               ])
+
+               blocks.add([
+                       "^<![A-Z]".to_re,
+                       ">".to_re
+               ])
+
+               blocks.add([
+                       "^<!\\[CDATA\\[".to_re,
+                       "\\]\\]>".to_re
+               ])
+
+               var re5_opening = "^</?(address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(\\s|[/]?[>]|$)".to_re
+               re5_opening.ignore_case = true
+               blocks.add([re5_opening, null])
+
+               var p_tagname = "[A-Za-z][A-Za-z0-9-]*"
+               var p_attribute_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*"
+               var p_uquoted_value = "[^\"'=<>`\\x00-\\x20]+"
+               var p_squoted_value = "'[^']*'"
+               var p_dquoted_value = "\"[^\"]*\""
+               var p_attribute_value = "({p_uquoted_value}|{p_squoted_value}|{p_dquoted_value})"
+               var p_attribute_value_spec = "(\\s*=\\s*{p_attribute_value})"
+               var p_attribute = "(\\s{p_attribute_name}{p_attribute_value_spec}?)"
+               var p_opentag = "<{p_tagname}{p_attribute}*\\s*/?>"
+               var p_closetag = "</{p_tagname}\\s*[>]"
+               var re6_opening = "^({p_opentag}|{p_closetag})\\s*$".to_re
+               re6_opening.ignore_case = true
+               blocks.add([re6_opening, null])
+
+               return blocks
+       end
+end
+
+redef class Int
+
+       # Tab stop is 4
+       private fun columns_to_next_tab_stop: Int do return 4 - (self % 4)
+end
+
+redef class String
+
+       # Is this string blank?
+       #
+       # i.e. contains only spacing characters.
+       private fun is_blank: Bool do
+               for i in [0 .. length[ do
+                       var c = chars[i]
+                       if c == ' ' or c == '\t' or c == '\n' or c == '\r' then
+                               continue
+                       else
+                               return false
+                       end
+               end
+               return true
+       end
+
+       # Is the character at `index` a space or a tab
+       #
+       # Return false if `index > self.length`.
+       private fun is_space_or_tab(index: Int): Bool do
+               if index >= length then return false
+               var c = chars[index]
+               return c == ' ' or c == '\t'
+       end
+end
diff --git a/lib/markdown2/markdown_github.nit b/lib/markdown2/markdown_github.nit
new file mode 100644 (file)
index 0000000..2239953
--- /dev/null
@@ -0,0 +1,117 @@
+# 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.
+
+# Markdown Github mode
+#
+# Enables:
+# * strike processing: ~strike~
+# * super processing: ^super^
+#
+# TODO table
+# TODO todo lists
+module markdown_github
+
+intrude import markdown_inline_parsing
+intrude import markdown_block_parsing
+
+redef class MdParser
+
+       # Enable Github mode
+       var github_mode = false is writable
+
+       redef var inline_parser is lazy do
+               var parser = super
+               parser.github_mode = github_mode
+               return parser
+       end
+end
+
+redef class MdInlineParser
+
+       # Enable Github mode
+       private var github_mode = false
+
+       redef var delimiter_processors is lazy do
+               var delimiters = super
+               if github_mode then
+                       delimiters.add new MdStrikeProcessor
+                       delimiters.add new MdSuperProcessor
+               end
+               return delimiters
+       end
+end
+
+# Strike processor
+class MdStrikeProcessor
+       super MdEmphasisDelimiterProcessor
+       noautoinit
+
+       redef var delimiter_char = '~'
+       redef var min_length = 1
+       redef fun delimiter_use(opener, closer) do return opener.original_length
+
+       redef fun process(opener, closer, delimiter_use) do
+               var node = new MdStrike(
+                               new MdLocation(
+                                       opener.location.line_start,
+                                       opener.location.column_start,
+                                       closer.location.line_end,
+                                       closer.location.column_end),
+                       opening_delimiter.to_s * delimiter_use)
+               var tmp = opener.next
+               while tmp != null and tmp != closer do
+                       var next = tmp.next
+                       node.append_child(tmp)
+                       tmp = next
+               end
+               opener.insert_after(node)
+       end
+end
+
+#  Striked text
+class MdStrike
+       super MdDelimited
+end
+
+# Super processor
+class MdSuperProcessor
+       super MdEmphasisDelimiterProcessor
+       noautoinit
+
+       redef var delimiter_char = '^'
+       redef var min_length = 1
+       redef fun delimiter_use(opener, closer) do return opener.original_length
+
+       redef fun process(opener, closer, delimiter_use) do
+               var node = new MdSuper(
+                       new MdLocation(
+                               opener.location.line_start,
+                               opener.location.column_start,
+                               closer.location.line_end,
+                               closer.location.column_end),
+                       opening_delimiter.to_s * delimiter_use)
+               var tmp = opener.next
+               while tmp != null and tmp != closer do
+                       var next = tmp.next
+                       node.append_child(tmp)
+                       tmp = next
+               end
+               opener.insert_after(node)
+       end
+end
+
+# Super text
+class MdSuper
+       super MdDelimited
+end
diff --git a/lib/markdown2/markdown_html_rendering.nit b/lib/markdown2/markdown_html_rendering.nit
new file mode 100644 (file)
index 0000000..11addf6
--- /dev/null
@@ -0,0 +1,458 @@
+# 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.
+
+# HTML rendering of Markdown documents
+module markdown_html_rendering
+
+import markdown_rendering
+import markdown_github
+import markdown_wikilinks
+
+# Markdown document renderer to HTML
+class HtmlRenderer
+       super MdRenderer
+
+       # HTML output under construction
+       private var html: Buffer is noinit
+
+       # Render `document` as HTML
+       redef fun render(document) do
+               reset
+               enter_visit(document)
+               return html.write_to_string
+       end
+
+       redef fun visit(node) do node.render_html(self)
+
+       # Reset `headings` and internal state
+       fun reset do
+               html = new Buffer
+               if enable_heading_ids then headings.clear
+       end
+
+       # Last char visited
+       #
+       # Used to avoid double blank lines.
+       private var last_char: nullable Char = null
+
+       # Add `string` to `html`
+       private fun add(string: String) do
+               html.append(string)
+               if not html.is_empty then
+                       last_char = html.last
+               end
+       end
+
+       # Add a raw `html` string to the output
+       #
+       # Raw means that the string will not be escaped.
+       fun add_raw(html: String) do add html
+
+       # Add `text` string to the output
+       #
+       # The string will be escaped.
+       fun add_text(text: String) do add html_escape(text, true)
+
+       # Add a blank line to the output
+       fun add_line do
+               if last_char != null and last_char != '\n' then
+                       add "\n"
+               end
+       end
+
+       # Escape `string` to HTML
+       #
+       # When `keep_entities`, HTML entities will not be escaped.
+       fun html_escape(string: String, keep_entities: Bool): String do
+               var buf: nullable Buffer = null
+               for i in [0..string.length[ do
+                       var c = string.chars[i]
+                       var sub = null
+                       if c == '&' and (not keep_entities or string.search_from(re_entity, i) == null) then
+                               sub = "&amp;"
+                       else if c == '<' then
+                               sub = "&lt;"
+                       else if c == '>' then
+                               sub = "&gt;"
+                       else if c == '"' then
+                               sub = "&quot;"
+                       else
+                               if buf != null then buf.add c
+                               continue
+                       end
+                       if buf == null then
+                               buf = new Buffer
+                               for j in [0..i[ do buf.add string.chars[j]
+                       end
+                       buf.append sub
+               end
+
+               if buf == null then return string
+               return buf.to_s
+       end
+
+       # HTML entity pattern
+       private var re_entity: Regex = "^&(#x[a-f0-9]\{1,8\}|#[0-9]\{1,8\}|[a-z][a-z0-9]\{1,31\});".to_re
+
+       # Encode the `uri` string
+       fun encode_uri(uri: String): String do
+               var buf = new Buffer
+
+               var i = 0
+               while i < uri.length do
+                       var c = uri.chars[i]
+                       if (c >= '0' and c <= '9') or
+                          (c >= 'a' and c <= 'z') or
+                          (c >= 'A' and c <= 'Z') or
+                          c == ';' or c == ',' or c == '/' or c == '?' or
+                          c == ':' or c == '@' or c == '=' or c == '+' or
+                          c == '$' or c == '-' or c == '_' or c == '.' or
+                          c == '!' or c == '~' or c == '*' or c == '(' or
+                          c == ')' or c == '#' or c == '\''
+                       then
+                               buf.add c
+                       else if c == '&' then
+                               buf.append "&amp;"
+                       else if c == '%' and uri.search_from(re_uri_code, i) != null then
+                               buf.append uri.substring(i, 3)
+                               i += 2
+                       else
+                               var bytes = c.to_s.bytes
+                               for b in bytes do buf.append "%{b.to_i.to_hex}".to_upper
+                       end
+                       i += 1
+               end
+
+               return buf.to_s
+       end
+
+       # URI encode pattern
+       private var re_uri_code: Regex = "^%[a-zA-Z0-9]\{2\}".to_re
+
+       # Add `id` tags to headings
+       var enable_heading_ids = false is optional, writable
+
+       # Associate headings ids to blocks
+       var headings = new ArrayMap[String, MdHeading]
+
+       # Strip heading id
+       fun strip_id(text: String): String do
+               # strip id
+               var b = new FlatBuffer
+               for c in text do
+                       if c == ' ' then
+                               b.add '_'
+                       else
+                               if not c.is_letter and
+                                  not c.is_digit and
+                                  not allowed_id_chars.has(c) then continue
+                               b.add c
+                       end
+               end
+               var res = b.to_s
+               if res.is_empty then res = "_"
+               var key = res
+               # check for multiple id definitions
+               if headings.has_key(key) then
+                       var i = 1
+                       key = "{res}_{i}"
+                       while headings.has_key(key) do
+                               i += 1
+                               key = "{res}_{i}"
+                       end
+               end
+               return key
+       end
+
+       # Allowed characters in ids
+       var allowed_id_chars: Array[Char] = ['-', '_', ':', '.']
+end
+
+redef class MdNode
+
+       # Render `self` as HTML
+       fun render_html(v: HtmlRenderer) do visit_all(v)
+end
+
+# Blocks
+
+redef class MdBlockQuote
+       redef fun render_html(v) do
+               v.add_line
+               v.add_raw "<blockquote>"
+               v.add_line
+               visit_all(v)
+               v.add_line
+               v.add_raw "</blockquote>"
+               v.add_line
+       end
+end
+
+redef class MdCodeBlock
+       redef fun render_html(v) do
+               var info = self.info
+               v.add_line
+               v.add_raw "<pre>"
+               v.add_raw "<code"
+               if info != null and not info.is_empty then
+                       v.add_raw " class=\"language-{info.split(" ").first}\""
+               end
+               v.add_raw ">"
+               var literal = self.literal or else ""
+               var lines = literal.split("\n")
+               for i in [0..lines.length[ do
+                       var line = lines[i]
+                       v.add_raw v.html_escape(line, false)
+                       if i < lines.length - 1 then
+                               v.add_raw "\n"
+                       end
+               end
+               v.add_raw "</code>"
+               v.add_raw "</pre>"
+               v.add_line
+       end
+end
+
+redef class MdHeading
+       redef fun render_html(v) do
+               v.add_line
+               if v.enable_heading_ids then
+                       var id = self.id
+                       if id == null then
+                               id = v.strip_id(title)
+                               v.headings[id] = self
+                               self.id = id
+                       end
+                       v.add_raw "<h{level} id=\"{id}\">"
+               else
+                       v.add_raw "<h{level}>"
+               end
+               visit_all(v)
+               v.add_raw "</h{level}>"
+               v.add_line
+       end
+
+       #
+       var id: nullable String = null
+
+       #
+       fun title: String do
+               var v = new RawTextVisitor
+               return v.render(self)
+       end
+end
+
+redef class MdUnorderedList
+       redef fun render_html(v) do
+               v.add_line
+               v.add_raw "<ul>"
+               v.add_line
+               visit_all(v)
+               v.add_line
+               v.add_raw "</ul>"
+               v.add_line
+       end
+end
+
+redef class MdOrderedList
+       redef fun render_html(v) do
+               var start = self.start_number
+               v.add_line
+               v.add_raw "<ol"
+               if start != 1 then
+                       v.add_raw " start=\"{start}\""
+               end
+               v.add_raw ">"
+               v.add_line
+               visit_all(v)
+               v.add_line
+               v.add_raw "</ol>"
+               v.add_line
+       end
+end
+
+redef class MdListItem
+       redef fun render_html(v) do
+               v.add_raw "<li>"
+               visit_all(v)
+               v.add_raw "</li>"
+               v.add_line
+       end
+end
+
+redef class MdParagraph
+       redef fun render_html(v) do
+               var is_tight = is_in_tight_list
+               if not is_tight then
+                       v.add_line
+                       v.add_raw "<p>"
+               end
+               visit_all(v)
+               if not is_tight then
+                       v.add_raw "</p>"
+                       v.add_line
+               end
+       end
+end
+
+redef class MdThematicBreak
+       redef fun render_html(v) do
+               v.add_line
+               v.add_raw "<hr />"
+               v.add_line
+       end
+end
+
+redef class MdHtmlBlock
+       redef fun render_html(v) do
+               v.add_line
+               var literal = self.literal or else ""
+               var lines = literal.split("\n")
+               for i in [0..lines.length[ do
+                       var line = lines[i]
+                       if not line.trim.is_empty then
+                               v.add_raw line
+                       end
+                       if i < lines.length - 1 then
+                               v.add_raw "\n"
+                       end
+               end
+               v.add_line
+       end
+end
+
+# Inlines
+
+redef class MdHardLineBreak
+       redef fun render_html(v) do
+               v.add_raw "<br />"
+               v.add_line
+       end
+end
+
+redef class MdSoftLineBreak
+       redef fun render_html(v) do
+               v.add_raw "\n"
+       end
+end
+
+redef class MdCode
+       redef fun render_html(v) do
+               v.add_raw "<code>"
+               v.add_raw v.html_escape(literal, false)
+               v.add_raw "</code>"
+       end
+end
+
+redef class MdEmphasis
+       redef fun render_html(v) do
+               v.add_raw "<em>"
+               visit_all(v)
+               v.add_raw "</em>"
+       end
+end
+
+redef class MdStrongEmphasis
+       redef fun render_html(v) do
+               v.add_raw "<strong>"
+               visit_all(v)
+               v.add_raw "</strong>"
+       end
+end
+
+redef class MdHtmlInline
+       redef fun render_html(v) do
+               v.add_raw literal
+       end
+end
+
+redef class MdImage
+       redef fun render_html(v) do
+               var url = self.destination
+               var title = self.title
+               v.add_raw "<img"
+               v.add_raw " src=\"{v.encode_uri(url)}\""
+
+               var alt_text = self.alt_text
+               v.add_raw " alt=\"{alt_text}\""
+
+               if title != null and not title.is_empty then
+                       v.add_raw " title=\""
+                       v.add_text title
+                       v.add_raw "\""
+               end
+
+               v.add_raw " />"
+       end
+
+       private fun alt_text: String do
+               var v = new RawTextVisitor
+               return v.render(self)
+       end
+end
+
+redef class MdLink
+       redef fun render_html(v) do
+               var url = self.destination
+               var title = self.title
+               v.add_raw "<a"
+               v.add_raw " href=\"{v.encode_uri(url)}\""
+               if title != null and not title.is_empty then
+                       v.add_raw " title=\""
+                       v.add_text title
+                       v.add_raw "\""
+               end
+               v.add_raw ">"
+               visit_all(v)
+               v.add_raw "</a>"
+       end
+end
+
+redef class MdText
+       redef fun render_html(v) do
+               v.add_text literal
+       end
+end
+
+# Github mode
+
+redef class MdStrike
+       redef fun render_html(v) do
+               v.add_raw "<del>"
+               visit_all(v)
+               v.add_raw "</del>"
+       end
+end
+
+redef class MdSuper
+       redef fun render_html(v) do
+               v.add_raw "<sup>"
+               visit_all(v)
+               v.add_raw "</sup>"
+       end
+end
+
+# Wikilinks mode
+
+redef class MdWikilink
+
+       # Dummy rendering of wikilinks
+       #
+       # Clients should redefine this.
+       redef fun render_html(v) do
+               v.add_raw "<wiki link=\"{v.encode_uri(link)}\">"
+               visit_all(v)
+               v.add_raw "</wiki>"
+       end
+end
diff --git a/lib/markdown2/markdown_inline_parsing.nit b/lib/markdown2/markdown_inline_parsing.nit
new file mode 100644 (file)
index 0000000..703f46e
--- /dev/null
@@ -0,0 +1,1401 @@
+# 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.
+
+# Parser for inline markdown
+#
+# Used to create the AST representation of inline nodes like emphasis, code, links
+# images etc.
+module markdown_inline_parsing
+
+import markdown_ast
+
+# Parser for inline content (text, links, emphasis, etc)
+class MdInlineParser
+
+       # List of delimiter processors to use
+       private var delimiter_processors: Array[MdDelimiterProcessor] is lazy do
+               var delimiters = new Array[MdDelimiterProcessor]
+               delimiters.add new MdAsteriskDelimiterProcessor
+               delimiters.add new MdUnderscoreDelimiterProcessor
+               return delimiters
+       end
+
+       # Map special characters to their delimiter processor
+       private var delimiter_processors_map: Map[Char, MdDelimiterProcessor] is lazy do
+               var map = new HashMap[Char, MdDelimiterProcessor]
+               for delimiter_processor in delimiter_processors do
+                       add_delimiter_processor(delimiter_processor, map)
+               end
+               special_characters.add_all map.keys
+               return map
+       end
+
+       # Register a delimiter processor
+       private fun add_delimiter_processor(delimiter_processor: MdDelimiterProcessor, map: Map[Char, MdDelimiterProcessor]) do
+               var opening = delimiter_processor.opening_delimiter
+               var closing = delimiter_processor.closing_delimiter
+               if opening == closing then
+                       if map.has_key(opening) then
+                               var old = map[opening]
+                               if old.opening_delimiter == old.closing_delimiter then
+                                       var s: MdStaggeredDelimiterProcessor
+                                       if old isa MdStaggeredDelimiterProcessor then
+                                               s = old
+                                       else
+                                               s = new MdStaggeredDelimiterProcessor(opening)
+                                               s.add old
+                                       end
+                                       s.add delimiter_processor
+                                       map[opening] = s
+                               else
+                                       add_delimiter_processor_for_char(opening, delimiter_processor, map)
+                               end
+                       else
+                               add_delimiter_processor_for_char(opening, delimiter_processor, map)
+                       end
+               else
+                       add_delimiter_processor_for_char(opening, delimiter_processor, map)
+                       add_delimiter_processor_for_char(closing, delimiter_processor, map)
+               end
+       end
+
+       # Register a delimiter processor for a special character
+       private fun add_delimiter_processor_for_char(delimiter_char: Char, delimiter_processor: MdDelimiterProcessor, map: Map[Char, MdDelimiterProcessor]) do
+               assert not map.has_key(delimiter_char) else
+                       print "Delimiter processor conflict with delimiter char `{delimiter_char}`"
+               end
+               map[delimiter_char] = delimiter_processor
+       end
+
+       # List of characters that have a special Markdown meaning
+       private var special_characters: Array[Char] = ['\n', '`', '[', ']', '\\', '!', '<', '&']
+
+       # Link references by ID, needs to be built up using `parse_reference` before calling `parse`
+       private var reference_map = new HashMap[String, MdLink]
+
+       # Current block under parsing
+       private var block: MdNode is noinit
+
+       # Current input string
+       private var input: String is noinit
+
+       # Current index
+       private var index: Int is noinit
+
+       # Current line
+       private var line: Int is noinit
+
+       # Current column
+       private var column: Int is noinit
+
+       # Current column offset
+       private var column_offset: Int is noinit
+
+       # Top delimiter (emphasis, strong emphasis or custom emphasis)
+       # Brackets are on a separate stack, different from the algorithm described in the spec.
+       private var last_delimiter: nullable MdDelimiter = null
+
+       # Top opening bracket (`[` or `![`)
+       private var last_bracket: nullable MdBracket = null
+
+       # Parse `input` as inline and add resulting nodes as children to `block`
+       fun parse(input: String, offset: Int, block: MdNode) do
+               self.block = block
+               self.input = input.trim
+               self.index = 0
+               self.last_delimiter = null
+               self.last_bracket = null
+               self.line = block.location.line_start
+               self.column_offset = offset
+               self.column = 1 + column_offset
+
+               var more_to_parse = parse_inline
+               while more_to_parse do
+                       more_to_parse = parse_inline
+               end
+
+               process_delimiters(null)
+               merge_child_text_nodes(block)
+       end
+
+       # Advance the current index of `count` characters
+       private fun advance(count: Int) do
+               index += count
+               column += count
+       end
+
+       # Attempt to parse a link reference
+       #
+       # Return how many characters were parsed as a reference.
+       # Returns 0 if none.
+       fun parse_reference(input: String): Int do
+               self.input = input
+               self.index = 0
+               self.column = 0
+               var dest
+               var title
+               var match_chars
+               var start_index = index
+
+               # label
+               match_chars = parse_link_label
+               if match_chars == 0 then return 0
+               advance match_chars
+
+               var raw_label = input.substring(0, match_chars)
+
+               # colon
+               if peek != ':' then return 0
+               advance 1
+
+               # link url
+               spnl
+
+               dest = parse_link_destination.first
+               if dest == null or dest.is_empty then return 0
+
+               var before_title = index
+               var before_column = column
+               spnl
+               title = parse_link_title
+               if title == null then
+                       # rewind before spaces
+                       index = before_title
+                       column = before_column
+               end
+
+               var at_line_end = true
+               if index != input.length and match(re_line_end) == null then
+                       if title == null then
+                               at_line_end = false
+                       else
+                               # the potential title we found is not at the line end,
+                               # but it could still be a legal link reference if we discard the title
+                               title = null
+                               # rewind before spaces
+                               index = before_title
+                               column = before_column
+                               # and instead check if the link URL is at the line end
+                               at_line_end = match(re_line_end) != null
+                       end
+               end
+
+               if not at_line_end then return 0
+
+               var normalized_label = raw_label.normalize_reference
+               if normalized_label.is_empty then return 0
+
+               if not reference_map.has_key(normalized_label) then
+                       var link = new MdLink(new MdLocation(0, 0, 0, 0), dest, title)
+                       reference_map[normalized_label] = link
+               end
+
+               return index - start_index
+       end
+
+       # Line end pattern
+       private var re_line_end: Regex = "^ *(\n|$)".to_re
+
+       # Append standard text to the current block
+       #
+       # Read `text` between `begin_index` and `end_index`.
+       private fun append_text(text: String, begin_index, end_index: nullable Int): MdText do
+               var node: MdText
+               if begin_index != null and end_index != null then
+                       var nb_chars = end_index - begin_index
+                       var string = text.substring(begin_index, nb_chars)
+                       node = new MdText(
+                               new MdLocation(
+                                       line,
+                                       column,
+                                       line,
+                                       column + nb_chars - 1
+                               ), string)
+               else
+                       node = new MdText(
+                               new MdLocation(
+                                       line,
+                                       column,
+                                       line,
+                                       column + text.length
+                               ), text)
+               end
+               append_node(node)
+               return node
+       end
+
+       # Append `node` to the current block
+       private fun append_node(node: MdNode) do block.append_child(node)
+
+       # Parse the next inline element in subject, advancing input index
+       #
+       # On success, add the result to block's children and return true.
+       # On failure, return false.
+       private fun parse_inline: Bool do
+               var res: Bool
+               var c = peek
+               if c == '\0' then return false
+               if c == '\n' then
+                       res = parse_newline
+               else if c == '\\' then
+                       res = parse_backslash
+               else if c == '`' then
+                       res = parse_backticks
+               else if c == '[' then
+                       res = parse_open_bracket
+               else if c == '!' then
+                       res = parse_bang
+               else if c == ']' then
+                       res = parse_close_bracket
+               else if c == '<' then
+                       res = parse_auto_link or parse_html_inline
+               else if c == '&' then
+                       res = parse_entity
+               else
+                       if delimiter_processors_map.has_key(c) then
+                               res = parse_delimiters(delimiter_processors_map[c], c)
+                       else
+                               res = parse_string
+                       end
+               end
+
+               if not res then
+                       advance 1
+                       # When we get here, it's only for a single special character that turned
+                       # out to not have a special meaning.
+                       # So we shouldn't have a single surrogate here, hence it should be ok
+                       # to turn it into a String
+                       var literal = c.to_s
+                       append_text(literal)
+               end
+
+               return true
+       end
+
+       # If `re` matches at current index in the input, advance index and return the match
+       # Else return null.
+       private fun match(re: Pattern): nullable String do
+               if index >= input.length then return null
+               var match = input.search_from(re, index)
+               if match != null then
+                       index = match.after
+                       column = match.after
+                       return match.to_s
+               end
+               return null
+       end
+
+       # Return the char at the current input index, or `\0`
+       private fun peek: Char do
+               if index < input.length then
+                       return input.chars[index]
+               end
+               return '\0'
+       end
+
+       # Return the char at the current input index + 1, or `\0`
+       private fun peek_next: Char do
+               if index + 1 < input.length then
+                       return input.chars[index + 1]
+               end
+               return '\0'
+       end
+
+       # Parse zero or more space characters, incuding at most one newline
+       private fun spnl: Bool do
+               var found_nl = false
+               loop
+                       var c = peek
+                       if c == ' ' or c == '\t' then
+                               advance 1
+                               continue
+                       else if c == '\n' then
+                               if found_nl then break
+                               found_nl = true
+                               advance 1
+                               continue
+                       end
+                       break
+               end
+               return true
+       end
+
+       # Parse a new line
+       #
+       # If it was preceded by two spaces, return a hard line break,
+       # otherwise a soft line break
+       private fun parse_newline: Bool do
+               advance 1 # assume we're at a `\n`
+
+               var last_child = block.last_child
+
+               # check previous text for trailing spaces
+               # the `has_suffix` is an optimization to avoid an RE match in the common case
+               if last_child != null and last_child isa MdText and
+                  (last_child.literal.has_suffix(" ")) then
+                       var text = last_child
+                       var literal = text.literal
+                       var match = literal.search(re_final_space)
+                       var spaces = if match != null then match.length else 0
+                       if spaces > 0 then
+                               text.literal = literal.substring(0, literal.length - spaces)
+                       end
+                       last_child.location.column_end = last_child.location.column_end - spaces
+                       if spaces >= 2 then
+                               append_node(new MdHardLineBreak(new MdLocation(line, column - spaces - 1, line, column - 1), false))
+                       else
+                               append_node(new MdSoftLineBreak(new MdLocation(line, column - spaces - 1, line, column -1)))
+                       end
+               else
+                       append_node(new MdSoftLineBreak(new MdLocation(line, column - 1, line, column - 1)))
+               end
+               line += 1
+               column = 1 + column_offset
+
+               # gobble leading spaces in next line
+               while peek == ' ' do
+                       advance 1
+               end
+               return true
+       end
+
+       # Final white spaces pattern
+       private var re_final_space: Regex = " *$".to_re
+
+       # Parse a backslash-escaped special character
+       #
+       # Add either the escaped characters, a hard line break (if the backslash is followed by
+       # a new line), or a literal backslash to the block's children.
+       private fun parse_backslash: Bool do
+               advance 1
+               if peek == '\n' then
+                       append_node(new MdHardLineBreak(new MdLocation(line, column - 1, line, column), true))
+                       advance 1
+                       line += 1
+                       column = 1 + column_offset
+               else if index < input.length and input.substring(index, 1).has(re_escapable) then
+                   append_text(input, index, index + 1)
+                   advance 1
+               else
+                       append_text("\\")
+               end
+               return true
+       end
+
+       # Escapable characters pattern
+       private var p_escapable = "[]!\"#$%&\'()*+,./:;<=>?@\\[\\\\^_`\\\{|\\\}~-]"
+
+       # Escapable characters regex
+       private var re_escapable: Regex = "^{p_escapable}".to_re
+
+       # Attempt to parse backticks
+       #
+       # Adding either a backtick code span or a literal sequence of backticks.
+       private fun parse_backticks: Bool do
+               var column_before = column
+               var ticks = match(re_ticks_here)
+               if ticks == null then return false
+
+               var after_open_ticks = index
+               var matched = match(re_ticks)
+               while matched != null do
+                       if matched == ticks then
+                               var content = input.substring(after_open_ticks, index - after_open_ticks - ticks.length)
+                               content = content.trim
+                               content = content.replace(re_whitespace, " ")
+                               var node = new MdCode(new MdLocation(line, column_before, line, column), matched.to_s, content.trim)
+                               append_node(node)
+                               column += 1
+                               return true
+                       end
+                       matched = match(re_ticks)
+               end
+               # If we got here, we didn't match a closing backtick sequence
+               index = after_open_ticks
+               column = after_open_ticks + 1
+               append_text(ticks)
+               return true
+       end
+
+       # Backticks starting pattern
+       private var re_ticks_here: Regex = "^`+".to_re
+
+       # Backticks pattern
+       private var re_ticks: Regex = "`+".to_re
+
+       # Attempt to parse delimiters like emphasis, strong emphasis or custom delimiters
+       private fun parse_delimiters(delimiter_processor: MdDelimiterProcessor, delimiter_char: Char): Bool do
+               var res = scan_delimiters(delimiter_processor, delimiter_char)
+               if res == null then return false
+
+               var length = res.count
+               var start_index = index
+               var start_column = column
+
+               advance length
+               var column_before = column
+               column = start_column
+               var node = append_text(input, start_index, index)
+               column = column_before
+
+               # Add entry to stack for this opener
+               var last_delimiter = new MdDelimiter(node, delimiter_char, res.can_open, res.can_close, last_delimiter)
+               last_delimiter.length = length
+               last_delimiter.original_length = length
+
+               var prev = last_delimiter.prev
+               if prev != null then
+                       prev.next = last_delimiter
+               end
+               self.last_delimiter = last_delimiter
+               return true
+       end
+
+       # Add open bracket to delimiter stack and add a text node to block's children
+       private fun parse_open_bracket: Bool do
+               var start_index = index
+               advance 1
+
+               var node = append_text("[")
+
+               # Add entry to stack for this opener
+               add_bracket(new MdBracket.link(node, start_index, column - 1, last_bracket, last_delimiter))
+               return true
+       end
+
+       # If next character is `[`, add `!` delimiter to delimiter stack and add a text node to
+       # block's children.
+       # Otherwise just add a text node.
+       private fun parse_bang: Bool do
+               var start_index = index
+               advance 1
+
+               if peek == '[' then
+                       advance 1
+                       var node = append_text("![")
+
+                       # Add entry to stack for this opener
+                       add_bracket(new MdBracket.image(node, start_index + 1, column - 2, last_bracket, last_delimiter))
+               else
+                       append_text("!")
+               end
+               return true
+       end
+
+       # Try match close bracket against an opening delimiter stack
+       #
+       # Add either a link or image, or a plan `[` character, to block's children.
+       # If there is a matching delimiter, remove it from the delimiter stack.
+       private fun parse_close_bracket: Bool do
+               advance 1
+               var start_index = index
+               var start_column = column
+
+               # Get previous `[` or `![`
+               var opener = last_bracket
+               if opener == null then
+                       # no matching opener, just return a literal
+                       append_text("]")
+                       return true
+               end
+
+               if not opener.allowed then
+                       # matching opener but it's not allowed, juste return a literal
+                       append_text("]")
+                       remove_last_bracket
+                       return true
+               end
+
+               # check to see if we have a link or image
+               var dest: nullable Couple[nullable String, Bool] = null
+               var title = null
+               var is_link_or_image = false
+
+               # maybe an inline link like `[foo](\uri "title")`
+               if peek == '(' then
+                       advance 1
+                       spnl
+                       dest = parse_link_destination
+                       if dest.first != null then
+                               spnl
+                               # title needs a whitespace before
+                               if input.substring(index - 1, 1).has(re_whitespace) then
+                                       title = parse_link_title
+                                       spnl
+                               end
+                               if peek == ')' then
+                                       advance 1
+                                       is_link_or_image = true
+                               else
+                                       index = start_index
+                                       column = start_column
+                               end
+                       end
+               end
+
+               # maybe a reference link like `[foo][bar]`, `[foo][]` or `[foo]`
+               if not is_link_or_image then
+                       # see if there's a link label like `[bar]` or `[]`
+                       var before_label = index
+                       var label_length = parse_link_label
+                       advance label_length
+                       var ref = null
+                       if label_length > 2 then
+                               ref = input.substring(before_label, label_length)
+                       else if not opener.bracket_after then
+                               # If the second label is empty `[foo][]` or missing `[foo]`, then the first label
+                               # is the reference.
+                               # But it can only be a reference when there's no (unescaped) bracket in it.
+                               # If there is, we don't even need to try to lookup the reference.
+                               ref = input.substring(opener.index, start_index - opener.index)
+                       end
+
+                       if ref != null then
+                               var nref = ref.normalize_reference
+                               if reference_map.has_key(nref) then
+                                       var link = reference_map[nref]
+                                       dest = new Couple[nullable String, Bool](link.destination, false)
+                                       title = link.title
+                                       is_link_or_image = true
+                               end
+                       end
+               end
+
+               if is_link_or_image then
+                       # If we got here, open is a potential opener
+                       var link_or_image: MdLinkOrImage
+                       if opener.is_image then
+                               link_or_image = new MdImage(new MdLocation(line, opener.column, line, column - 1), dest.as(not null).first or else "", title)
+                       else
+                               link_or_image = new MdLink(new MdLocation(line, opener.column, line, column - 1), dest.as(not null).first or else "", title)
+                       end
+                       link_or_image.has_brackets = dest.as(not null).second
+
+                       var node = opener.node.next
+                       while node != null do
+                               var next = node.next
+                               link_or_image.append_child(node)
+                               node = next
+                       end
+                       append_node(link_or_image)
+
+                       # Process delimiters such as emphasis inside a link/image
+                       process_delimiters(opener.prev_delimiter)
+                       merge_child_text_nodes(link_or_image)
+                       # We don't need the corresponding text node anymore, we turned it into a node
+                       opener.node.unlink
+                       remove_last_bracket
+
+                       # Links within links are not allowed
+                       # We found this link, so there can be no other link around it.
+                       if not opener.is_image then
+                               var bracket = last_bracket
+                               while bracket != null do
+                                       if not bracket.is_image then
+                                               # disallow link opener
+                                               bracket.allowed = false
+                                       end
+                                       bracket = bracket.prev
+                               end
+                       end
+                       return true
+               end
+
+               if not is_link_or_image then
+                       if parse_wikilink then return true
+               end
+
+               # no link or image
+               append_text("]")
+               remove_last_bracket
+               index = start_index
+               column = start_column
+               return true
+       end
+
+       # Whitespace pattern
+       private var re_whitespace: Regex = "\\s+".to_re
+
+       # Add a bracket token on top of the `last_bracket` stack
+       private fun add_bracket(bracket: MdBracket) do
+               var last_bracket = self.last_bracket
+               if last_bracket != null then
+                       last_bracket.bracket_after = true
+               end
+               self.last_bracket = bracket
+       end
+
+       # Remove the last bracket on the `last_bracket` stack
+       private fun remove_last_bracket do
+               var last_bracket = self.last_bracket
+               if last_bracket == null then return
+               self.last_bracket = last_bracket.prev
+       end
+
+       # Wikilink placeholder
+       #
+       # Will be defined in sub module.
+       private fun parse_wikilink: Bool do return false
+
+       # Attempt to parse a link destination, returning the string or null if not match
+       private fun parse_link_destination: Couple[nullable String, Bool] do
+               var buffer = new Buffer
+
+               var c = peek
+               var parens = 0
+
+               var has_bracket = c == '<'
+               if has_bracket then advance 1
+
+               loop
+                       c = peek
+                       if c == '\0' then
+                               break # end of input
+                       else if c == ' ' or c == '\t' or c == '\n' or c == '\r' then
+                               break # no spaces allowed in urls
+                       else if c == '\\' then
+                               var next = peek_next
+                               if escapable.has(next) then
+                                       buffer.add next
+                                       advance 2 # skip over the backslash
+                                       continue
+                               end
+                       else if has_bracket and c == '>' then
+                               advance 1
+                               break
+                       else if not has_bracket and c == '(' then
+                               parens += 1
+                       else if not has_bracket and c == ')' then
+                               if parens == 0 then break
+                               parens -= 1
+                       else if c == '\0' then
+                               break
+                       end
+                       buffer.add c
+                       advance 1
+               end
+               return new Couple[nullable String, Bool](buffer.to_s, has_bracket)
+       end
+
+       # Attempt to parse a link title (sans quotes), returning the string or null if no match
+       private fun parse_link_title: nullable String do
+               var c = peek
+               if c != '\'' and c != '"' and c != '(' then
+                       return null
+               end
+               var opener = c
+
+               var buffer = new Buffer
+               loop
+                       advance 1
+                       c = peek
+                       if c == opener or (opener == '(' and c == ')') then
+                               advance 1
+                               break
+                       else if c == '\\' then
+                               var next = peek_next
+                               if escapable.has(next) then
+                                       buffer.add next
+                                       advance 1
+                                       continue
+                               end
+                       else if c == '\0' then
+                               return null
+                       end
+                       buffer.add c
+               end
+               return buffer.to_s
+       end
+
+       # Escapable characters
+       private var escapable = "[]!\"#$%&\'()*+,./:;<=>?@\\^_`\{|\}~-"
+
+       # Attempt to parse a link label returning number of characters parsed
+       private fun parse_link_label: Int do
+               var i = index
+               while i < input.length do
+                       var c = input[i]
+                       if i == index and c != '[' then
+                               return 0
+                       else if c == '[' and i != index then
+                               if input[i - 1] != '\\' or (i - 2 > index and input[i - 2] == '\\') then
+                                       return 0
+                               end
+                       else if c == ']' then
+                               if i > 1001 then return 0
+                               if input[i - 1] != '\\' or (i - 2 > index and input[i - 2] == '\\') then
+                                       return (i - index) + 1
+                               end
+                       end
+                       i += 1
+               end
+               return 0
+       end
+
+       # Attempt to parse an autolink (URL or email in pointy brackets)
+       private fun parse_auto_link: Bool do
+               var column_before = column
+               var m = match(re_autolink_email)
+               if m != null then
+                       var dest = m.substring(1, m.length - 2)
+                       var node = new MdLink(new MdLocation(line, column_before, line, column), "mailto:{dest}", null, true)
+                       node.append_child(new MdText(new MdLocation(line, column_before + 1, line, column - 1), dest))
+                       column += 1
+                       append_node(node)
+                       return true
+               end
+               m = match(re_autolink_url)
+               if m != null then
+                       var dest = m.substring(1, m.length - 2)
+                       var node = new MdLink(new MdLocation(line, column_before, line, column), dest, null, true)
+                       node.append_child(new MdText(new MdLocation(line, column_before + 1, line, column - 1), dest))
+                       column += 1
+                       append_node(node)
+                       return true
+               end
+               return false
+       end
+
+       # Autolink email pattern
+       private var re_autolink_email: Regex = "^<([a-zA-Z0-9.!#$%&'*+/=?^_`\{|\}~-]+@[a-zA-Z0-9]([a-zA-Z0-9-]\{0,61\}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]\{0,61\}[a-zA-Z0-9])?)*)>".to_re
+
+       # Autolink url pattern
+       private var re_autolink_url: Regex = "^<[a-zA-Z][a-zA-Z0-9.+-]\{1,31\}:[^<> ]*>".to_re
+
+       # Attempt to parse an inline HTML string
+       private fun parse_html_inline: Bool do
+               var column_before = column
+               var m = match(re_html_tag)
+               if m != null then
+                       var node = new MdHtmlInline(new MdLocation(line, column_before, line, column), m)
+                       column += 1
+                       append_node(node)
+                       return true
+               end
+               return false
+       end
+
+       private var p_tagname = "[A-Za-z][A-Za-z0-9-]*"
+       private var p_attribute_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*"
+       private var p_uquoted_value = "[^\"'=<>` \t\n]+"
+       private var p_squoted_value = "'[^']*'"
+       private var p_dquoted_value = "\"[^\"]*\""
+       private var p_attribute_value = "({p_uquoted_value}|{p_squoted_value}|{p_dquoted_value})"
+       private var p_attribute_value_spec = "(\\s*=\\s*{p_attribute_value})"
+       private var p_attribute = "(\\s{p_attribute_name}{p_attribute_value_spec}?)"
+       private var p_opentag = "<{p_tagname}{p_attribute}*\\s*/?>"
+       private var p_closetag = "</{p_tagname}\\s*[>]"
+       private var p_html_comment = "<!---->|<!--(-?[^>-])(-?[^-])*-->"
+       private var p_processing_instruction = "[<][?].*?[?][>]"
+       private var p_declaration = "<![A-Z]+\\s+[^>]*>"
+       private var p_cdata = "<!\\[CDATA\\[.*\\]\\]>"
+       private var p_html_tag = "({p_opentag}|{p_closetag}|{p_html_comment}|{p_processing_instruction}|{p_declaration}|{p_cdata})"
+
+       # HTML tag pattern
+       private var re_html_tag: Regex do
+               var re = "^{p_html_tag}".to_re
+               re.ignore_case = true
+               return re
+       end
+
+       # Attempt to parse an HTML entity
+       private fun parse_entity: Bool do
+               var m = match(re_entity_here)
+               if m != null then
+                       append_text(m)
+                       return true
+               end
+               return false
+       end
+
+       # HTML entity pattern
+       private var re_entity_here: Regex do
+               var re = "^&(#x[a-f0-9]\{1,8\}|#[0-9]\{1,8\}|[a-z][a-z0-9]\{1,31\});".to_re
+               re.ignore_case = true
+               return re
+       end
+
+       # Parse a run of ordinary characters
+       #
+       # Or a single character with a special meaning in markdown, as a plain string.
+       private fun parse_string: Bool do
+               var begin = index
+               var begin_column = column
+               var length = input.length
+               while index != length do
+                       if special_characters.has(input.chars[index]) then
+                               break
+                       end
+                       advance 1
+               end
+               if begin != index then
+                       var column_before = column
+                       column = begin_column
+                       append_text(input, begin, index)
+                       column = column_before
+                       return true
+               end
+               return false
+       end
+
+       # Scan a sequence of characters with code `delimiter_char`
+       #
+       # Return information about the number of delimiters and whether they are positioned
+       # such as they can open and/or close emphasis or strong emphasis.
+       private fun scan_delimiters(delimiter_processor: MdDelimiterProcessor, delimiter_char: Char): nullable MdDelimiterData do
+               var start_index = index
+               var start_column = column
+
+               var delimiter_count = 0
+               while peek == delimiter_char do
+                       delimiter_count += 1
+                       advance 1
+               end
+
+               if delimiter_count < delimiter_processor.min_length then
+                       index = start_index
+                       column = start_column
+                       return null
+               end
+
+               var before = "\n"
+               if start_index > 0 then
+                       before = input.substring(start_index - 1, 1)
+               end
+
+               var char_after = peek
+               var after = "\n"
+               if char_after != '\0' then
+                       after = char_after.to_s
+               end
+
+               var before_is_punctuation = before.has(re_punctuation)
+               var before_is_whitespace = before.has(re_whitespace_char)
+               var after_is_punctuation = after.has(re_punctuation)
+               var after_is_whitespace = after.has(re_whitespace_char)
+
+               var left_flanking = not after_is_whitespace and
+                       (not after_is_punctuation or before_is_whitespace or before_is_punctuation)
+               var right_flanking = not before_is_whitespace and
+                       (not before_is_punctuation or after_is_whitespace or after_is_punctuation)
+
+               var can_open
+               var can_close
+               if delimiter_char == '_' then
+                       can_open = left_flanking and (not right_flanking or before_is_punctuation)
+                       can_close = right_flanking and (not left_flanking or after_is_punctuation)
+               else
+                       can_open = left_flanking and delimiter_char == delimiter_processor.opening_delimiter
+                       can_close = right_flanking and delimiter_char == delimiter_processor.closing_delimiter
+               end
+
+               index = start_index
+               column = start_column
+               return new MdDelimiterData(delimiter_count, can_open, can_close)
+       end
+
+       # Punctuation pattern
+       private var re_punctuation: Regex = "^[]!\"#\\$%&'()*+,.:;<=>?@^_`\{|\}~[-]".to_re
+
+       # Whitespace character start pattern
+       private var re_whitespace_char: Regex = "^[  \t\r\n]".to_re
+
+       # Process the stack of delimiters
+       private fun process_delimiters(stack_bottom: nullable MdDelimiter) do
+               var openers_bottom = new HashMap[Char, nullable MdDelimiter]
+
+               # find first closer above stack bottom
+               var closer = last_delimiter
+               while closer != null and closer.prev != stack_bottom do
+                       closer = closer.prev
+               end
+               # move forward, looking for closers, and handling each
+               while closer != null do
+                       var delimiter_char = closer.delimiter_char
+
+                       if not closer.can_close then
+                               closer = closer.next
+                               continue
+                       end
+
+                       if not delimiter_processors_map.has_key(delimiter_char) then
+                               closer = closer.next
+                               continue
+                       end
+
+                       var delimiter_processor = delimiter_processors_map[delimiter_char]
+                       var opening_delimiter_char = delimiter_processor.opening_delimiter
+
+                       # Found delimiter closer. Now look back for first matching opener
+                       var use_delims = 0
+                       var opener_found = false
+                       var potential_opener_found = false
+                       var opener = closer.prev
+
+                       while opener != null and opener != stack_bottom and (not openers_bottom.has_key(delimiter_char) or opener != openers_bottom[delimiter_char]) do
+
+                               if opener.can_open and opener.delimiter_char == opening_delimiter_char then
+                                       potential_opener_found = true
+                                       use_delims = delimiter_processor.delimiter_use(opener, closer)
+                                       if use_delims > 0 then
+                                               opener_found = true
+                                               break
+                                       end
+                               end
+                               opener = opener.prev
+                       end
+
+                       if not opener_found then
+                               if not potential_opener_found then
+                                       # Set lower bound for future searches for openers.
+                                       # Only do this when we didn't even have a potential opener
+                                       # (one that matches the character and can open).
+                                       # If an opener was rejected because of the number of delimiters
+                                       # (e.g. because of the "multiple of 3" rule),
+                                       # we want to consider it next time because the number of delimiter
+                                       # can change as we continue processing.
+                                       openers_bottom[delimiter_char] = closer.prev
+                                       if not closer.can_open then
+                                               # We can remove a closer that can't be an opener,
+                                               # once we've seen there's no matching opener.
+                                               remove_delimiters_keep_node(closer)
+                                       end
+                               end
+                               closer = closer.next
+                               continue
+                       end
+
+                       var opener_node = opener.as(not null).node
+                       var closer_node = closer.node
+
+                       # Remove number of used delimieters from stack and inline nodes
+                       opener.as(not null).length -= use_delims
+                       closer.length -= use_delims
+                       opener_node.literal = opener_node.literal.substring(0,
+                               opener_node.literal.length - use_delims)
+                       closer_node.literal = closer_node.literal.substring(0,
+                               closer_node.literal.length - use_delims)
+
+                       remove_delimiters_between(opener, closer)
+                       # The delimieter processor can re-parent the nodes between opener and closer,
+                       # so make sure they're contiguous already.
+                       # Exclusive because we want to keep opener/closer themselves.
+                       merge_text_nodes_between_exclusive(opener_node, closer_node)
+                       delimiter_processor.process(opener_node, closer_node, use_delims)
+
+                       # Node delimieter characters left to process, so we can remove
+                       # delimieter and the now empty node
+                       if opener.as(not null).length == 0 then
+                               remove_delimiters_and_node(opener)
+                       end
+
+                       if closer.length == 0 then
+                               var next = closer.next
+                               remove_delimiters_and_node(closer)
+                               closer = next
+                       end
+               end
+
+               # Remove all delimiters
+               while last_delimiter != null and last_delimiter != stack_bottom do
+                       remove_delimiters_keep_node(last_delimiter)
+               end
+       end
+
+       # Remove all delimiters between `opener` and `closer`
+       private fun remove_delimiters_between(opener, closer: nullable MdDelimiter) do
+               if opener == null or closer == null then return
+
+               var delimiter = closer.prev
+               while delimiter != null and delimiter != opener do
+                       var previous_delimiter = delimiter.prev
+                       remove_delimiters_keep_node(delimiter)
+                       delimiter = previous_delimiter
+               end
+       end
+
+       # Remove the delimiter and the corresponding text node
+       #
+       # For used delimiters, e.g. `*` in `*foo*`.
+       private fun remove_delimiters_and_node(delim: nullable MdDelimiter) do
+               if delim == null then return
+
+               var node = delim.node
+               node.unlink
+               remove_delimiter(delim)
+       end
+
+       # Remove the delimiter but keep the corresponding node as text
+       #
+       # For unused delimiters such as `_` in `foo_bar`.
+       private fun remove_delimiters_keep_node(delim: nullable MdDelimiter) do
+               remove_delimiter(delim)
+       end
+
+       # Remove the delimiter `delim`
+       private fun remove_delimiter(delim: nullable MdDelimiter) do
+               if delim == null then return
+
+               var prev = delim.prev
+               if prev != null then
+                       prev.next = delim.next
+               end
+               var next = delim.next
+               if next == null then
+                       # top of stack
+                       last_delimiter = prev
+               else
+                       next.prev = prev
+               end
+       end
+
+       # Merge all nodes between `from` and `to` excluding `from` and `to`
+       private fun merge_text_nodes_between_exclusive(from, to: nullable MdNode) do
+               if from == null or to == null then return
+               # no node between them
+               if from == to or from.next == to then return
+               merge_text_nodes_inclusive(from.next, to.prev)
+       end
+
+       # Merge all child nodes of `node` into one
+       private fun merge_child_text_nodes(node: nullable MdNode) do
+               if node == null then return
+               # no children or just one child node, no need for merging
+               if node.first_child == node.last_child then return
+               merge_text_nodes_inclusive(node.first_child, node.last_child)
+       end
+
+       # Merge all nodes between `from` and `to` including `from` and `to`
+       private fun merge_text_nodes_inclusive(from, to: nullable MdNode) do
+               var first = null
+               var last = null
+
+               var node = from
+               while node != null do
+                       if node isa MdText then
+                               var text = node
+                               if first == null then first = text
+                               last = text
+                       else
+                               merge_if_needed(first, last)
+                               first = null
+                               last = null
+                       end
+                       if node == to then break
+                       node = node.next
+               end
+               merge_if_needed(first, last)
+       end
+
+       # Merge all nodes between `first` and `last`
+       private fun merge_if_needed(first, last: nullable MdText) do
+               if first != null and last != null and first != last then
+                       var buffer = new Buffer
+                       buffer.append(first.literal)
+                       var node = first.next
+                       var stop = last.next
+                       while node != null and node != stop do
+                               buffer.append(node.as(MdText).literal)
+                               first.location.line_end = node.location.line_end
+                               first.location.column_end = node.location.column_end
+                               var unlink = node
+                               node = node.next
+                               unlink.unlink
+                       end
+                       var literal = buffer.write_to_string
+                       first.literal = literal
+               end
+       end
+end
+
+# Custom delimiter processor for additional delimiters besides `_` and `*`
+interface MdDelimiterProcessor
+
+       # The character that marks the beginning of a delimited node
+       #
+       # Must not clash with anu built-in special characters.
+       fun opening_delimiter: Char is abstract
+
+       # The character that marks the ending of a delimited node
+       #
+       # Must not clash with anu built-in special characters.
+       fun closing_delimiter: Char is abstract
+
+       # Minimum number of delimiters characters that are needed to active this
+       #
+       # Must be at least one.
+       fun min_length: Int is abstract
+
+       # Determine how many (if any) of the delimiter characters should be used
+       #
+       # This allows implementations to decide how many characters to use based on the
+       # properties of the delimiter runs.
+       #
+       # An implementation can also return 0 when it doesn't want to allow this particular
+       # combination of delimiter runs.
+       fun delimiter_use(opener, closer: MdDelimiter): Int is abstract
+
+       # Process the matched delimiters
+       #
+       # For example, by wrapping the nodes between `opener` and `closer` in a new node,
+       # or appending a new node after the opener.
+       #
+       # Note that removal of the delimiter from the delimiter nodes and unlinking
+       # them is done by the caller.
+       fun process(opener, closer: MdText, delimiter_use: Int) is abstract
+end
+
+# A delimiter is one or more of the same delimiter character
+#
+# Used for paired delimiters like emphasis or strong emphasis.
+class MdDelimiter
+
+       # Node containing the delimiter
+       var node: MdText
+
+       # Character used as delimiter
+       var delimiter_char: Char
+
+       # Can `self` open a delimiter?
+       var can_open: Bool
+
+       # Cant `self` close a delimiter?
+       var can_close: Bool
+
+       # Previous delimiter found
+       var prev: nullable MdDelimiter
+
+       # Next delimiter found
+       var next: nullable MdDelimiter
+
+       # The number of characters in this delimiter run that are left for processing
+       var length = 1
+
+       # The number of characters originally in this delimiter run
+       #
+       # At the start of processing, this is the same as `length`.
+       var original_length = 1
+end
+
+# Opening bracket for links and images
+class MdBracket
+
+       # Node containing the bracket
+       var node: MdText
+
+       # Index of the bracket in the original string
+       var index: Int
+
+       # COlumn of the bracket
+       var column: Int
+
+       # Is this bracket opening an image?
+       var is_image: Bool
+
+       # Previous bracket
+       var prev: nullable MdBracket
+
+       # Previous delimiter
+       var prev_delimiter: nullable MdDelimiter
+
+       # Whether this bracket is allowed to form a link/image
+       var allowed = true
+
+       # Whether there is an unescaped bracket (opening or closing) anywhere after this bracket
+       var bracket_after = false
+
+       # Create a new bracket for a link
+       init link(node: MdText, index: Int, column: Int, prev: nullable MdBracket, prev_delimiter: nullable MdDelimiter) do
+               init(node, index, column, false, prev, prev_delimiter)
+       end
+
+       # Create a new bracket for an image
+       init image(node: MdText, index: Int, column: Int, prev: nullable MdBracket, prev_delimiter: nullable MdDelimiter) do
+               init(node, index, column, true, prev, prev_delimiter)
+       end
+end
+
+# Data about a delimiter parsing
+private class MdDelimiterData
+
+       # Number of successive delimiters found
+       var count: Int
+
+       # Can this delimiter open an inline construct?
+       var can_open: Bool
+
+       # Can this delimiter close an inline construct?
+       var can_close: Bool
+end
+
+# An implementation of MdDelimiterProcessor that dispatches all calls to others
+#
+# The sub processors called bepends on the length of the delimiter run.
+# All child processors must have different minimum lengths.
+# A given delimiter run is dispatched to the child with the largest acceptable minimum length.
+# If not child is applicable, the one with the largest minimum length is chosen.
+class MdStaggeredDelimiterProcessor
+       super MdDelimiterProcessor
+
+       # Delimiter character
+       var delim: Char
+
+       # Sub processors to apply
+       var processors = new Array[MdDelimiterProcessor]
+
+       redef var min_length = 0
+       redef fun opening_delimiter do return delim
+       redef fun closing_delimiter do return delim
+
+       # Add a new sub delimiter processor
+       fun add(dp: MdDelimiterProcessor) do
+               var len = dp.min_length
+               var i = 0
+               while i < processors.length do
+                       var p = processors[i]
+                       assert len != p.min_length else
+                               print "Cannot add two delimiter processor for `{delim}` " +
+                                       "and mininimum length `{len}`"
+                       end
+                       if len > p.min_length then
+                               break
+                       end
+                       i += 1
+               end
+               processors.insert(dp, i)
+       end
+
+       # Find the corresponding processor for a length of `len` delimiter characters
+       fun find_processor(len: Int): MdDelimiterProcessor do
+               for processor in processors do
+                       if processor.min_length <= len then return processor
+               end
+               return processors.first
+       end
+
+       redef fun delimiter_use(opener, closer) do
+               return find_processor(opener.length).delimiter_use(opener, closer)
+       end
+
+       redef fun process(opener, closer, delimiter_use) do
+               find_processor(delimiter_use).process(opener, closer, delimiter_use)
+       end
+end
+
+# A processor for emphasis tokens
+class MdEmphasisDelimiterProcessor
+       super MdDelimiterProcessor
+
+       # Delimiter character
+       var delimiter_char: Char
+
+       redef var min_length = 1
+       redef fun opening_delimiter do return delimiter_char
+       redef fun closing_delimiter do return delimiter_char
+
+       redef fun delimiter_use(opener, closer) do
+               # "multiple of 3" rule for internal delimiter runs
+               if (opener.can_close or closer.can_open) and
+                  ((opener.original_length + closer.original_length) % 3 == 0) then
+                       return 0
+               end
+               # calculate actual number of delimiters used from this closer
+               if opener.length >= 2 and closer.length >= 2 then
+                       return 2
+               end
+               return 1
+       end
+
+       redef fun process(opener, closer, delimiter_use) do
+               var single_delimiter = opening_delimiter.to_s
+               var emphasis: MdNode
+               if delimiter_use == 1 then
+                       emphasis = new MdEmphasis(
+                               new MdLocation(
+                                       opener.location.line_start,
+                                       opener.location.column_start,
+                                       closer.location.line_end,
+                                       closer.location.column_end),
+                               single_delimiter)
+               else
+                       emphasis = new MdStrongEmphasis(
+                               new MdLocation(
+                                       opener.location.line_start,
+                                       opener.location.column_start + opener.literal.length,
+                                       closer.location.line_end,
+                                       closer.location.column_end - closer.literal.length),
+                               "{single_delimiter}{single_delimiter}")
+               end
+               var tmp = opener.next
+               while tmp != null and tmp != closer do
+                       var next = tmp.next
+                       emphasis.append_child(tmp)
+                       tmp = next
+               end
+               opener.insert_after(emphasis)
+       end
+end
+
+# Asterisk delimiters processor
+class MdAsteriskDelimiterProcessor
+       super MdEmphasisDelimiterProcessor
+       noautoinit
+
+       redef var delimiter_char = '*'
+end
+
+# Underscore delimters processor
+class MdUnderscoreDelimiterProcessor
+       super MdEmphasisDelimiterProcessor
+       noautoinit
+
+       redef var delimiter_char = '_'
+end
+
+# Utils
+
+redef class String
+
+       # Remove escape backslash from string
+       fun unescape_string: String do
+               if not has(re_escaped) then return self
+
+               var buffer = new Buffer
+               var match = search(re_escaped)
+               var last_end = 0
+               while match != null do
+                       buffer.append substring(last_end, match.from - last_end)
+                       buffer.append substring(match.from + 1, 1)
+                       last_end = match.after
+                       match = search_from(re_escaped, last_end)
+               end
+               if last_end < length then
+                       buffer.append substring(last_end, length - last_end)
+               end
+               return buffer.to_s
+       end
+
+       # Normalize link reference names
+       private fun normalize_reference: String do
+               var stripped = self.substring(1, length - 2).trim
+               var lowercase = stripped.to_lower # TODO utf-8
+               return lowercase.replace(re_whitespace, " ")
+       end
+end
+
+redef class Sys
+       private var p_escapable = "[]!\"#$%&\'()*+,./:;<=>?@\\[\\\\^_`\\\{|\\\}~-]"
+       private var re_escaped: Regex = "\\\\{p_escapable}".to_re
+       private var re_whitespace: Regex = "\\s+".to_re
+end
diff --git a/lib/markdown2/markdown_latex_rendering.nit b/lib/markdown2/markdown_latex_rendering.nit
new file mode 100644 (file)
index 0000000..b7c4abd
--- /dev/null
@@ -0,0 +1,438 @@
+# 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.
+
+# LaTeX rendering of Markdown documents
+module markdown_latex_rendering
+
+import markdown_rendering
+import markdown_github
+import markdown_wikilinks
+
+# Markdown document renderer to LaTeX
+class LatexRenderer
+       super MdRenderer
+
+       # Generate the LaTeX document wrapper
+       #
+       # The header includes:
+       #  * document class
+       #  * package importation
+       #  * begin and end document directives
+       var wrap_document = false is optional, writable
+
+       # LaTeX document class
+       #
+       # Default is `article`.
+       var document_class = "article" is optional, writable
+
+       # LaTeX document page format
+       #
+       # Default is `letter`.
+       var page_format = "letter" is optional, writable
+
+       # LaTeX font size
+       #
+       # Default is `10pt`.
+       var font_size = "10pt" is optional, writable
+
+       # Use `listings` package for code blocks?
+       var use_listings = false is optional, writable
+
+       # LaTeX output under construction
+       private var latex: Buffer is noinit
+
+       # Render `document` as LaTeX
+       redef fun render(document) do
+               latex = new Buffer
+               enter_visit(document)
+               return latex.write_to_string
+       end
+
+       redef fun visit(node) do node.render_latex(self)
+
+       # Indentation level
+       var indent = 0
+
+       # Add a raw `string` to the output
+       #
+       # Raw means that the string will not be escaped.
+       fun add_raw(string: String) do latex.append string
+
+       # Add `text` string to the output
+       #
+       # The string will be escaped.
+       fun add_text(text: String) do latex.append latex_escape(text)
+
+       # Add a blank line to the output
+       fun add_line do
+               if not latex.is_empty and latex.last != '\n' then
+                       latex.add '\n'
+               end
+       end
+
+       # Add an indentation depending on `ident` level
+       fun add_indent do latex.append " " * indent
+
+       # Escape `string` to LaTeX
+       fun latex_escape(string: String): String do
+               var buffer = new Buffer
+               for i in [0 .. string.length[ do
+                       var c = string.chars[i]
+                       if c == '>' then
+                               buffer.append "\\textgreater"
+                               continue
+                       else if c == '<' then
+                               buffer.append "\\textless"
+                               continue
+                       else if c == '\\' then
+                               buffer.append "\\textbackslash"
+                               continue
+                       else if escaped_chars.has(c) then
+                               buffer.add '\\'
+                       end
+                       buffer.add c
+               end
+               return buffer.to_s
+       end
+
+       # LaTeX characters to escape
+       var escaped_chars = ['%', '$', '{', '}', '_', '#', '&']
+end
+
+redef class MdNode
+
+       # Render `self` as HTML
+       fun render_latex(v: LatexRenderer) do visit_all(v)
+end
+
+# Blocks
+
+redef class MdDocument
+       redef fun render_latex(v) do
+               var wrap_document = v.wrap_document
+               if v.wrap_document then
+                       v.add_line
+                       v.add_raw "\\documentclass[{v.page_format},{v.font_size}]\{{v.document_class}\}\n\n"
+                       v.add_raw "\\usepackage[utf8]\{inputenc\}\n"
+                       if v.use_listings then
+                               v.add_raw "\\usepackage\{listings\}\n"
+                       end
+                       v.add_raw "\\usepackage\{hyperref\}\n"
+                       v.add_raw "\\usepackage\{graphicx\}\n"
+                       v.add_raw "\\usepackage\{ulem\}\n\n"
+                       v.add_raw "\\begin\{document\}\n\n"
+               end
+               var node = first_child
+               while node != null do
+                       v.enter_visit node
+                       node = node.next
+                       if node != null then v.add_raw "\n"
+               end
+               if wrap_document then
+                       v.add_raw "\n\\end\{document\}\n"
+               end
+       end
+end
+
+redef class MdHeading
+       redef fun render_latex(v) do
+               var level = self.level
+               v.add_indent
+               v.add_line
+               if level == 1 then
+                       v.add_raw "\\section\{"
+               else if level == 2 then
+                       v.add_raw "\\subsection\{"
+               else if level == 3 then
+                       v.add_raw "\\subsubsection\{"
+               else if level == 4 then
+                       v.add_raw "\\paragraph\{"
+               else if level == 5 then
+                       v.add_raw "\\subparagraph\{"
+               else
+                       # use bold for level 6 headings
+                       v.add_raw "\\textbf\{"
+               end
+               v.add_indent
+               visit_all(v)
+               v.add_raw "\}"
+               v.add_line
+       end
+end
+
+redef class MdBlockQuote
+       redef fun render_latex(v) do
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{quote\}"
+               v.add_line
+               v.indent += 2
+               visit_all(v)
+               v.indent -= 2
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{quote\}"
+               v.add_line
+       end
+end
+
+redef class MdIndentedCodeBlock
+       redef fun render_latex(v) do
+               var directive = if v.use_listings then "lstlisting" else "verbatim"
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{{directive}\}"
+               v.add_line
+               v.add_raw literal or else ""
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{{directive}\}"
+               v.add_line
+       end
+end
+
+redef class MdFencedCodeBlock
+       redef fun render_latex(v) do
+               var info = self.info
+               var lstlistings = v.use_listings
+               var directive = if lstlistings then "lstlisting" else "verbatim"
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{{directive}\}"
+               if lstlistings and info != null and not info.is_empty then
+                       v.add_raw "[language={info}]"
+               end
+               v.add_line
+               v.add_raw literal or else ""
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{{directive}\}"
+               v.add_line
+       end
+end
+
+redef class MdOrderedList
+       redef fun render_latex(v) do
+               var start = self.start_number
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{enumerate\}"
+               v.indent += 2
+               v.add_line
+               if start != 1 then
+                       v.add_indent
+                       v.add_raw "\\setcounter\{enum{nesting_level}\}\{{start}\}"
+                       v.add_line
+               end
+               visit_all(v)
+               v.indent -= 2
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{enumerate\}"
+               v.add_line
+       end
+
+       # Depth of ordered list
+       #
+       # Used to compute the `setcounter` level.
+       fun nesting_level: String do
+               var nesting = 1
+
+               var parent = self.parent
+               while parent != null do
+                       if parent isa MdOrderedList then nesting += 1
+                       parent = parent.parent
+               end
+
+               if nesting <= 3 then
+                       return "i" * nesting
+               end
+               return "iv"
+       end
+end
+
+redef class MdUnorderedList
+       redef fun render_latex(v) do
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{itemize\}"
+               v.add_line
+               v.indent += 2
+               visit_all(v)
+               v.indent -= 2
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{itemize\}"
+               v.add_line
+       end
+end
+
+redef class MdListItem
+       redef fun render_latex(v) do
+               v.add_indent
+               v.add_raw "\\item"
+               v.add_line
+               v.indent += 2
+               visit_all(v)
+               v.indent -= 2
+               v.add_line
+       end
+end
+
+redef class MdThematicBreak
+       redef fun render_latex(v) do
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{center\}\\rule\{3in\}\{0.4pt\}\\end\{center\}"
+               v.add_line
+       end
+end
+
+redef class MdParagraph
+       redef fun render_latex(v) do
+               v.add_indent
+               visit_all(v)
+               v.add_line
+       end
+end
+
+
+redef class MdHtmlBlock
+       redef fun render_latex(v) do
+               v.add_line
+               v.add_indent
+               v.add_raw "\\begin\{verbatim\}"
+               v.add_line
+               v.add_indent
+               v.add_raw literal or else ""
+               v.add_line
+               v.add_indent
+               v.add_raw "\\end\{verbatim\}"
+               v.add_line
+       end
+end
+
+# Inlines
+
+redef class MdLineBreak
+       redef fun render_latex(v) do
+               v.add_line
+               v.add_indent
+       end
+end
+
+redef class MdCode
+       redef fun render_latex(v) do
+               v.add_raw "\\texttt\{"
+               v.add_text literal
+               v.add_raw "\}"
+       end
+end
+
+redef class MdEmphasis
+       redef fun render_latex(v) do
+               v.add_raw "\\textit\{"
+               visit_all(v)
+               v.add_raw "\}"
+       end
+end
+
+redef class MdStrongEmphasis
+       redef fun render_latex(v) do
+               v.add_raw "\\textbf\{"
+               visit_all(v)
+               v.add_raw "\}"
+       end
+end
+
+redef class MdHtmlInline
+       redef fun render_latex(v) do
+               v.add_raw "\\texttt\{"
+               v.add_raw v.latex_escape(literal)
+               v.add_raw "\}"
+       end
+end
+
+redef class MdImage
+       redef fun render_latex(v) do
+               v.add_raw "\\includegraphics\{"
+               v.add_text destination
+               v.add_raw "\}"
+       end
+
+       private fun alt_text: String do
+               var v = new RawTextVisitor
+               return v.render(self)
+       end
+end
+
+redef class MdLink
+       redef fun render_latex(v) do
+               if is_autolink then
+                       v.add_raw "\\url\{"
+                       v.add_text destination
+                       v.add_raw "\}"
+                       return
+               end
+               var title = self.title
+               v.add_raw "\\href\{"
+               v.add_text destination
+               v.add_raw "\}\{"
+               visit_all(v)
+               if title != null and not title.is_empty then
+                       v.add_raw " ("
+                       v.add_text title
+                       v.add_raw ")"
+               end
+               v.add_raw "\}"
+       end
+end
+
+redef class MdText
+       redef fun render_latex(v) do
+               v.add_text literal
+       end
+end
+
+# Github mode
+
+redef class MdStrike
+       redef fun render_latex(v) do
+               v.add_raw "\\sout\{"
+               visit_all(v)
+               v.add_raw "\}"
+       end
+end
+
+redef class MdSuper
+       redef fun render_latex(v) do
+               v.add_raw "\\textsuperscript\{"
+               visit_all(v)
+               v.add_raw "\}"
+       end
+end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_latex(v) do
+               v.add_raw "\\texttt\{"
+               var title = self.title
+               if title != null then
+                       v.add_text "{title} | "
+               end
+               v.add_text link
+               v.add_raw "\}"
+       end
+end
diff --git a/lib/markdown2/markdown_man_rendering.nit b/lib/markdown2/markdown_man_rendering.nit
new file mode 100644 (file)
index 0000000..1e047d6
--- /dev/null
@@ -0,0 +1,258 @@
+# 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.
+
+# Manpages rendering of Markdown documents
+module markdown_man_rendering
+
+import markdown_rendering
+import markdown_github
+import markdown_wikilinks
+
+# Markdown document renderer to Manpage
+class ManRenderer
+       super MdRenderer
+
+       # Output under construction
+       private var man: Buffer is noinit
+
+       # Render `node` as Markdown
+       redef fun render(node) do
+               man = new Buffer
+               enter_visit(node)
+               return man.write_to_string
+       end
+
+       redef fun visit(node) do node.render_man(self)
+
+       # Add `string` to `man`
+       fun add(string: String) do
+               man.append(string.replace("-", "\\-"))
+       end
+
+       # Add code that need to be escaped
+       fun add_code(code: String) do
+               add code.replace(" ", "\\ ")
+       end
+
+       # Add a blank line to the output
+       fun add_line do
+               add "\n"
+       end
+end
+
+redef class MdNode
+
+       # Render `self` as Manpage format
+       fun render_man(v: ManRenderer) do visit_all(v)
+end
+
+# Blocks
+
+redef class MdBlockQuote
+       redef fun render_man(v) do
+               v.add ".RS"
+               visit_all(v)
+               v.add ".RE"
+               v.add_line
+       end
+end
+
+redef class MdCodeBlock
+       redef fun render_man(v) do
+               v.add ".RS\n.nf\n\\f[C]"
+               v.add_line
+
+               var literal = self.literal
+               if literal != null then
+                       var lines = literal.split("\n")
+                       for i in [0 .. lines.length[ do
+                               if i == lines.length - 1 then break
+                               var line = lines[i]
+                               v.add_code line
+                               v.add_line
+                       end
+               end
+
+               v.add "\\f[]\n.fi\n.RE"
+               v.add_line
+       end
+end
+
+redef class MdHeading
+       redef fun render_man(v) do
+               var level = self.level
+
+               if level == 1 then
+                       v.add ".SH "
+               else if level == 2 then
+                       v.add ".SS "
+               else if level >= 3 then
+                       # We use dictionary (titled paragraph) to simulate a 3rd level (or more)
+                       v.add ".TP\n"
+               end
+               visit_all(v)
+               v.add_line
+       end
+end
+
+redef class MdUnorderedList
+       redef fun render_man(v) do
+               v.add ".RS"
+               v.add_line
+
+               var node = first_child
+               while node != null do
+                       v.add ".IP \\[bu] 3"
+                       v.add_line
+                       v.enter_visit node
+                       v.add_line
+                       node = node.next
+               end
+
+               v.add ".RE"
+               v.add_line
+       end
+end
+
+redef class MdOrderedList
+       redef fun render_man(v) do
+               v.add ".RS"
+               v.add_line
+
+               var index = start_number
+               var node = first_child
+               while node != null do
+                       v.add ".IP \"{index}.\" 3"
+                       v.add_line
+                       v.enter_visit node
+                       v.add_line
+                       node = node.next
+                       index += 1
+               end
+
+               v.add ".RE"
+               v.add_line
+       end
+end
+
+redef class MdParagraph
+       redef fun render_man(v) do
+               var in_list = is_in_list
+               if not in_list then
+                       v.add_line
+               end
+               visit_all(v)
+               if not in_list then
+                       v.add_line
+               end
+       end
+end
+
+redef class MdThematicBreak
+       redef fun render_man(v) do
+               v.add "***"
+               v.add_line
+       end
+end
+
+redef class MdHtmlBlock
+       redef fun render_man(v) do
+               v.add_line
+               v.add literal or else ""
+               v.add_line
+       end
+end
+
+# Inlines
+
+redef class MdLineBreak
+       redef fun render_man(v) do
+               v.add_line
+       end
+end
+
+redef class MdCode
+       redef fun render_man(v) do
+               v.add "\\f[C]"
+               v.add_code literal
+               v.add "\\f[]"
+       end
+end
+
+redef class MdEmphasis
+       redef fun render_man(v) do
+               v.add "\\f[I]"
+               visit_all(v)
+               v.add "\\f[]"
+       end
+end
+
+redef class MdStrongEmphasis
+       redef fun render_man(v) do
+               v.add "\\f[B]"
+               visit_all(v)
+               v.add "\\f[]"
+       end
+end
+
+redef class MdHtmlInline
+       redef fun render_man(v) do
+               v.add literal
+       end
+end
+
+redef class MdLinkOrImage
+       redef fun render_man(v) do
+               var title = self.title
+
+               visit_all(v)
+               v.add " ("
+               v.add destination
+               if title != null and not title.is_empty then
+                       v.add " "
+                       v.add title
+               end
+               v.add ")"
+       end
+end
+
+redef class MdText
+       redef fun render_man(v) do
+               v.add literal
+       end
+end
+
+# Github
+
+redef class MdStrike
+       redef fun render_man(v) do
+               v.add "[STRIKEOUT:"
+               visit_all(v)
+               v.add "]"
+       end
+end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_man(v) do
+               v.add "("
+               var title = self.title
+               if title != null then
+                       v.add "{title} | "
+               end
+               v.add link
+               v.add ")"
+       end
+end
diff --git a/lib/markdown2/markdown_md_rendering.nit b/lib/markdown2/markdown_md_rendering.nit
new file mode 100644 (file)
index 0000000..eadda1b
--- /dev/null
@@ -0,0 +1,392 @@
+# 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.
+
+# Markdown rendering of Markdown documents
+module markdown_md_rendering
+
+import markdown_rendering
+import markdown_github
+import markdown_wikilinks
+
+# Markdown document renderer to Markdown
+class MarkdownRenderer
+       super MdRenderer
+
+       # Markdown output under construction
+       private var md: Buffer is noinit
+
+       # Render `node` as Markdown
+       redef fun render(node) do
+               reset
+               enter_visit(node)
+               return md.write_to_string
+       end
+
+       redef fun visit(node) do node.render_md(self)
+
+       # Reset internal state
+       fun reset do
+               md = new Buffer
+       end
+
+       # Current indentation level
+       private var indent = 0
+
+       # Are we currently in a blockquote?
+       var in_quote = 0
+
+       # Add a `md` string to the output
+       fun add_raw(md: String) do self.md.append(md)
+
+       # Add a blank line to the output
+       fun add_line do add_raw "\n"
+
+       # Add an indentation depending on `ident` level
+       fun add_indent do
+               add_raw " " * indent
+       end
+end
+
+private class TextLengthVisitor
+       super MdVisitor
+
+       var length = 0
+
+       redef fun visit(node) do node.process_len(self)
+end
+
+redef class MdNode
+
+       # Render `self` as Markdown
+       fun render_md(v: MarkdownRenderer) do visit_all(v)
+
+       private fun process_len(v: TextLengthVisitor) do visit_all(v)
+end
+
+redef class MdDocument
+       redef fun render_md(v) do
+               var node = first_child
+               while node != null do
+                       v.enter_visit(node)
+                       node = node.next
+                       if node != null then
+                               v.add_line
+                       end
+               end
+       end
+end
+
+# Blocks
+
+redef class MdBlockQuote
+       redef fun render_md(v) do
+               v.in_quote += 1
+               var node = first_child
+               while node != null do
+                       v.add_indent
+                       v.add_raw "> "
+                       v.enter_visit(node)
+                       node = node.next
+               end
+               v.in_quote -= 1
+       end
+end
+
+redef class MdIndentedCodeBlock
+       redef fun render_md(v) do
+               var literal = self.literal
+               if literal == null then return
+
+               var lines = literal.split("\n")
+               for i in [0..lines.length[ do
+                       if i == lines.length - 1 then continue
+                       var line = lines[i]
+                       if line.is_empty then
+                               v.add_raw "\n"
+                       else
+                               v.add_indent
+                               if use_tabs then
+                                       v.add_raw "\t"
+                               else
+                                       v.add_raw " " * 4
+                               end
+                               v.add_raw line
+                               v.add_line
+                       end
+               end
+       end
+end
+
+redef class MdFencedCodeBlock
+       redef fun render_md(v) do
+               var info = self.info
+               v.add_indent
+               v.add_raw fence_char.to_s * fence_length
+               v.add_raw info or else ""
+               for line in (literal or else "").split("\n") do
+                       v.add_line
+                       if not line.is_empty then
+                               v.add_indent
+                       end
+                       v.add_raw line
+               end
+               v.add_indent
+               v.add_raw fence_char.to_s * fence_length
+               v.add_line
+       end
+end
+
+redef class MdHeading
+       redef fun render_md(v) do
+               if is_setext then
+                       visit_all(v)
+                       var length_visitor = new TextLengthVisitor
+                       length_visitor.enter_visit(self)
+                       v.add_line
+                       if level == 1 then
+                               v.add_raw "=" * length_visitor.length
+                       else
+                               v.add_raw "-" * length_visitor.length
+                       end
+               else
+                       v.add_raw "#" * level
+                       v.add_raw " "
+                       visit_all(v)
+                       if has_atx_trailing then
+                               v.add_raw " "
+                               v.add_raw "#" * level
+                       end
+               end
+               v.add_line
+       end
+end
+
+redef class MdOrderedList
+       # Children numbering
+       private var md_numbering: Int = start_number is lazy
+end
+
+redef class MdListItem
+       redef fun render_md(v) do
+               var parent = self.parent
+               var is_tight = parent.as(MdListBlock).is_tight
+
+               v.add_indent
+               if parent isa MdUnorderedList then
+                       v.add_raw parent.bullet_marker.to_s
+                       v.indent += 2
+               else if parent isa MdOrderedList then
+                       v.add_raw "{parent.md_numbering}{parent.delimiter.to_s}"
+                       v.indent += 3
+               end
+
+               var node = first_child
+               if node != null then
+                       v.add_raw " "
+               else
+                       v.add_line
+               end
+               while node != null do
+                       v.enter_visit(node)
+                       node = node.next
+                       if node != null and not is_tight then
+                               v.add_line
+                       end
+               end
+
+               if next != null and not is_tight then
+                       v.add_line
+               end
+
+               if parent isa MdUnorderedList then
+                       v.indent -= 2
+               else if parent isa MdOrderedList then
+                       parent.md_numbering += 1
+                       v.indent -= 3
+               end
+       end
+end
+
+redef class MdParagraph
+       redef fun render_md(v) do
+               if not parent isa MdBlockQuote and not parent isa MdListItem or prev != null then
+                       v.add_indent
+               end
+               # if parent isa MdBlockQuote then
+                       # v.add_raw "> "
+                       # var node = first_child
+                       # while node != null do
+                               # v.enter_visit(node)
+                               # if node isa MdSoftLineBreak or node isa MdHardLineBreak then
+                                       # v.add_raw "> "
+                               # end
+                               # node = node.next
+                       # end
+                       # v.add_line
+                       # return
+               # end
+               visit_all(v)
+               v.add_line
+       end
+end
+
+redef class MdThematicBreak
+       redef fun render_md(v) do
+               v.add_raw original_pattern
+               v.add_line
+       end
+end
+
+redef class MdHtmlBlock
+       redef fun render_md(v) do
+               v.add_raw literal or else ""
+               v.add_line
+       end
+end
+
+# Inlines
+
+redef class MdHardLineBreak
+       redef fun render_md(v) do
+               if has_backslash then
+                       v.add_raw "\\"
+               else
+                       v.add_raw "  "
+               end
+               v.add_line
+               v.add_indent
+               v.add_raw "> " * v.in_quote
+       end
+
+       redef fun process_len(v) do
+               super
+               v.length += 1
+       end
+end
+
+redef class MdSoftLineBreak
+       redef fun render_md(v) do
+               v.add_line
+               v.add_indent
+               v.add_raw "> " * v.in_quote
+       end
+
+       redef fun process_len(v) do
+               super
+               v.length += 1
+       end
+end
+
+redef class MdCode
+       redef fun render_md(v) do
+               v.add_raw delimiter
+               v.add_raw literal
+               v.add_raw delimiter
+       end
+
+       redef fun process_len(v) do
+               super
+               v.length += delimiter.length
+       end
+end
+
+redef class MdDelimited
+       redef fun render_md(v) do
+               v.add_raw delimiter
+               visit_all(v)
+               v.add_raw delimiter
+       end
+
+       redef fun process_len(v) do
+               super
+               v.length += delimiter.length * 2
+       end
+end
+
+redef class MdHtmlInline
+       redef fun render_md(v) do
+               v.add_raw literal
+       end
+
+       redef fun process_len(v) do
+               v.length += literal.length
+       end
+end
+
+redef class MdLinkOrImage
+       redef fun render_md(v) do
+               var title = self.title
+               v.add_raw "["
+               visit_all(v)
+               v.add_raw "]"
+               v.add_raw "("
+               if has_brackets then
+                       v.add_raw "<"
+               end
+               v.add_raw destination
+               if has_brackets then
+                       v.add_raw ">"
+               end
+               if title != null and not title.is_empty then
+                       v.add_raw " \""
+                       v.add_raw title.replace("\"", "\\\"")
+                       v.add_raw "\""
+               end
+               v.add_raw ")"
+       end
+end
+
+
+redef class MdImage
+       redef fun render_md(v) do
+               v.add_raw "!"
+               super
+       end
+end
+
+redef class MdLink
+       redef fun render_md(v) do
+               if is_autolink then
+                       v.add_raw "<"
+                       v.add_raw destination
+                       v.add_raw ">"
+                       return
+               end
+               super
+       end
+end
+
+redef class MdText
+       redef fun render_md(v) do
+               v.add_raw literal
+       end
+
+       redef fun process_len(v) do
+               v.length += literal.length
+       end
+end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_md(v) do
+               v.add_raw "[["
+               var title = self.title
+               if title != null then
+                       v.add_raw "{title} | "
+               end
+               v.add_raw link
+               v.add_raw "]]"
+       end
+end
diff --git a/lib/markdown2/markdown_rendering.nit b/lib/markdown2/markdown_rendering.nit
new file mode 100644 (file)
index 0000000..ff49d1c
--- /dev/null
@@ -0,0 +1,69 @@
+# 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.
+
+# Markdown document rendering
+module markdown_rendering
+
+import markdown_ast
+
+# Common interface for all markdown renderer
+interface MdRenderer
+       super MdVisitor
+
+       # Render `node`
+       fun render(node: MdNode): String is abstract
+end
+
+# A renderer that output raw text
+class RawTextVisitor
+       super MdRenderer
+
+       # Text under construction
+       private var text: Buffer is noinit
+
+       redef fun render(node) do
+               text = new Buffer
+               enter_visit(node)
+               return text.to_s
+       end
+
+       # Append `string` to `text`
+       fun add(string: String) do text.append(string)
+
+       redef fun visit(node) do node.render_raw_text(self)
+end
+
+redef class MdNode
+
+       # Return `self` as raw text
+       fun raw_text: String do
+               var v = new RawTextVisitor
+               return v.render(self)
+       end
+
+       # Render `self` as raw text
+       fun render_raw_text(v: RawTextVisitor) do visit_all(v)
+end
+
+redef class MdCode
+       redef fun render_raw_text(v) do v.add literal
+end
+
+redef class MdLineBreak
+       redef fun render_raw_text(v) do v.add "\n"
+end
+
+redef class MdText
+       redef fun render_raw_text(v) do v.add literal
+end
diff --git a/lib/markdown2/markdown_wikilinks.nit b/lib/markdown2/markdown_wikilinks.nit
new file mode 100644 (file)
index 0000000..d6cc3a0
--- /dev/null
@@ -0,0 +1,119 @@
+# 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.
+
+# Markdown wikilinks processing
+#
+# Enables parsing of `[[wikilinks]]` syntax.
+module markdown_wikilinks
+
+intrude import markdown_inline_parsing
+intrude import markdown_block_parsing
+
+redef class MdParser
+
+       # Enable wikilinks mode
+       var wikilinks_mode = false is writable
+
+       redef var inline_parser is lazy do
+               var parser = super
+               parser.wikilinks_mode = wikilinks_mode
+               return parser
+       end
+end
+
+redef class MdInlineParser
+
+       # Enable wikilinks mode
+       private var wikilinks_mode = false
+
+       redef fun parse_wikilink do
+               if not wikilinks_mode then return false
+
+               # do we have two opening bracket?
+               var last_bracket = self.last_bracket
+               if last_bracket == null then return false
+               var first_bracket = last_bracket.prev
+               if first_bracket == null then return false
+
+               # was the first bracket an image?
+               if first_bracket.is_image then return false
+
+               # do we have two closing brackets?
+               if index >= input.length or input.chars[index] != ']' then return false
+
+               advance 1 # skip last bracket
+               var start_index = first_bracket.index + 2
+               var end_index = index - 2
+
+               # create wikilink node
+               var content = input.substring(start_index, end_index - start_index)
+               var parts = content.split("|")
+               var title = if parts.length > 1 then parts.first.trim else null
+               var link = parts.last.trim
+
+               var wikilink = new MdWikilink(
+                               new MdLocation(
+                                       first_bracket.node.location.line_start,
+                                       first_bracket.node.location.column_start - 1,
+                                       line,
+                                       column - 1),
+                       link, title)
+
+               var node = last_bracket.node.next
+               var in_link = false
+               while node != null do
+                       var next = node.next
+                       if not in_link then
+                               if node isa MdText and node.literal.has("|") then
+                                       var buf = new Buffer
+                                       for c in node.literal.chars do
+                                               if c == '|' then
+                                                       in_link = true
+                                                       break
+                                               end
+                                               buf.add c
+                                       end
+                                       node.literal = buf.write_to_string.r_trim
+                               end
+                               wikilink.append_child(node)
+                       else
+                               node.unlink
+                       end
+                       node = next
+               end
+
+               append_node(wikilink)
+
+               # Process delimiters such as emphasis inside a link/image
+               process_delimiters(last_bracket.prev_delimiter)
+               merge_child_text_nodes(wikilink)
+
+               # remove brackets
+               first_bracket.node.unlink
+               last_bracket.node.unlink
+
+               return true
+       end
+end
+
+# A Wikilink node
+class MdWikilink
+       super MdNode
+
+       # Wikilink link
+       var link: String is writable
+
+       # Wikilink title
+       var title: nullable String = null is optional, writable
+end
diff --git a/lib/markdown2/nitmd.nit b/lib/markdown2/nitmd.nit
new file mode 100644 (file)
index 0000000..5a6970f
--- /dev/null
@@ -0,0 +1,73 @@
+# 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.
+
+# A Markdown parser for Nit.
+module nitmd
+
+import markdown_html_rendering
+import markdown_md_rendering
+import markdown_man_rendering
+import markdown_latex_rendering
+
+import config
+
+var opt_to = new OptionString("Specify output format (html, md, man, latex)", "-t", "--to")
+
+var usage = new Buffer
+usage.append "Usage: nitmd [-t format] [file.md]\n"
+usage.append "Translate Markdown documents to other formats.\n\n"
+usage.append "If no argument, read the Markdown input from `stdin`."
+
+var config = new Config
+config.add_option(opt_to)
+config.tool_description = usage.write_to_string
+
+config.parse_options(args)
+if config.args.length > 1 then
+       config.usage
+       exit 1
+end
+
+var md
+if config.args.is_empty then
+       md = sys.stdin.read_all
+else
+       var file = config.args.first
+       if not file.file_exists then
+               print "'{file}' not found"
+               exit 1
+       end
+       md = file.to_path.read_all
+end
+
+# Parse the input
+var parser = new MdParser
+var node = parser.parse(md)
+
+var renderer: MdRenderer
+var to = opt_to.value
+if to == null or to == "html" then
+       renderer = new HtmlRenderer
+else if to == "md" then
+       renderer = new MarkdownRenderer
+else if to == "man" then
+       renderer = new ManRenderer
+else if to == "latex" then
+       renderer = new LatexRenderer
+else
+       print "Unknown output format: {to}"
+       exit 1
+       return
+end
+printn renderer.render(node)
diff --git a/lib/markdown2/package.ini b/lib/markdown2/package.ini
new file mode 100644 (file)
index 0000000..a138d93
--- /dev/null
@@ -0,0 +1,12 @@
+[package]
+name=markdown2
+tags=format,lib
+maintainer=Alexandre Terrasa <alexandre@moz-code.org>
+license=Apache-2.0
+desc=A markdown parser for Nit
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/markdown2/
+git=https://github.com/nitlang/nit.git
+git.directory=lib/markdown2/
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
diff --git a/lib/markdown2/tests/commonmark_gen.nit b/lib/markdown2/tests/commonmark_gen.nit
new file mode 100644 (file)
index 0000000..efebd80
--- /dev/null
@@ -0,0 +1,251 @@
+# 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.
+
+# Generate Nitunit tests from commonmark specification.
+#
+# See the full specification and the test cases at <http://commonmark.org/>.
+#
+# Usage:
+#
+# ~~~sh
+# commonmark_gen <commonmark_tests.json> <output directory>
+# ~~~
+module commonmark_gen
+
+import json
+import json::static
+import template
+
+# Generate the test cases from the JSON testfile.
+class TestGenerator
+
+       # Input file in containing the tests in JSON format
+       var json_file: String
+
+       # Output directory where the Nitunit files will be generated
+       var output_dir: String
+
+       # Ignored tests
+       #
+       # We ignore some tests for two reasons:
+       # * because `nitmd` does not fully support UTF-8
+       # * because somes tests are wrong
+       var ignored_tests: Array[Int] do
+               var ignored = new Array[Int]
+               ignored.add_all([171, 304, 305, 306, 311, 312, 313, 477, 514]) # utf-8 tests
+               ignored.add_all([275, 276]) # spec is wrong compared to reference implementation
+               return ignored
+       end
+
+       # Load the tests files from the JSON input
+       fun load_tests: Map[String, Array[TestCase]] do
+               var json = json_file.to_path.read_all.parse_json
+               var tests = new HashMap[String, Array[TestCase]]
+
+               for obj in json.as(JsonArray) do
+                       if not obj isa JsonObject then continue
+
+                       var number = obj["example"].as(Int)
+                       if ignored_tests.has(number) then continue
+
+                       var name = "test{number}"
+
+                       var section = obj["section"].as(String)
+                       if not tests.has_key(section) then
+                               tests[section] = new Array[TestCase]
+                       end
+
+                       var markdown = obj["markdown"].as(String)
+                       markdown = markdown.replace("\\", "\\\\")
+                       markdown = markdown.replace("\n", "\\n")
+                       markdown = markdown.replace("\t", "\\t")
+
+                       # fix missing chars in some tests
+                       if number == 162 then
+                               markdown = markdown.replace("my url", "my%20url")
+                       else if number == 467 then
+                               markdown = markdown.replace("my uri", "my%20uri")
+                       end
+
+                       var html = obj["html"].as(String)
+                       html = html.replace("\\", "\\\\")
+                       html = html.replace("\n", "\\n")
+                       html = html.replace("\t", "\\t")
+
+                       tests[section].add(new TestCase(name, markdown, html))
+               end
+
+               return tests
+       end
+
+       # Generate the Nitunit test files
+       fun gen_tests do
+               var tests = load_tests
+
+               for section, test_cases in tests do
+                       var test_file = new TestFile("test_commonmark_{strip_module_name(section)}")
+                       var test_class = new TestClass("TestCommonmark{strip_class_name(section)}")
+                       test_class.test_cases.add_all test_cases
+                       test_file.test_classes.add test_class
+                       test_file.save(output_dir)
+               end
+       end
+
+       # Strip module name
+       #
+       # Used to create a Nitunit module name from a CommonMark section title.
+       fun strip_module_name(name: String): String do
+               var b = new FlatBuffer
+               for c in name do
+                       if c == ' ' then
+                               b.add '_'
+                       else
+                               if not c.is_letter and
+                                  not c.is_digit and
+                                  not allowed_id_chars.has(c) then continue
+                               b.add c.to_lower
+                       end
+               end
+               return b.to_s
+       end
+
+       # Strip class name
+       #
+       # Used to create a Nitunit test class name from a CommonMark section title.
+       fun strip_class_name(name: String): String do
+               var b = new FlatBuffer
+               var was_space = false
+               for c in name do
+                       if c == ' ' then
+                               was_space = true
+                       else
+                               if not c.is_letter and
+                                  not c.is_digit and
+                                  not allowed_id_chars.has(c) then continue
+                               if was_space then
+                                       b.add c.to_upper
+                                       was_space = false
+                               else
+                                       b.add c
+                               end
+                       end
+               end
+               return b.to_s
+       end
+
+       private var allowed_id_chars: Array[Char] = ['-', '_', ':', '.']
+end
+
+# A Nitunit test file
+class TestFile
+
+       # Test module name
+       var test_file_name: String
+
+       # Test classes in this module
+       var test_classes = new Array[TestClass]
+
+       # Copyright header and module declaration
+       fun header: String do
+               return """
+# 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.
+
+module {{{test_file_name}}} is test
+
+import test_markdown
+"""
+       end
+
+       # Render the test module as a Nit string
+       fun render: String do
+               var tpl = new Template
+               tpl.add header
+               for test_class in test_classes do
+                       tpl.add test_class.render
+               end
+               return tpl.write_to_string
+       end
+
+       # Save the test module in `directory
+       fun save(directory: String) do
+               render.write_to_file(directory / "{test_file_name}.nit")
+       end
+end
+
+# A Nitunit test class
+class TestClass
+
+       # Test class name
+       var test_class_name: String
+
+       # Test cases in this test class
+       var test_cases = new Array[TestCase]
+
+       # Render the test class as a Nit string
+       fun render: String do
+               var tpl = new Template
+               tpl.addn "\nclass {test_class_name}"
+               tpl.addn "\tsuper TestMarkdownHtml"
+               tpl.addn "\ttest"
+               for test_case in test_cases do
+                       tpl.add test_case.render
+               end
+               tpl.addn "end"
+               return tpl.write_to_string
+       end
+end
+
+# A Nitunit test case
+class TestCase
+
+       # Test method name
+       var test_name: String
+
+       # Markdown input
+       var markdown: String
+
+       # Expected html output
+       var html: String
+
+       # Render the test case as a Nit string
+       fun render: String do
+               var tpl = new Template
+               tpl.addn "\n\tfun {test_name} is test do"
+               tpl.addn "\t\tvar md = \"\"\"{markdown}\"\"\""
+               tpl.addn "\t\tvar html = \"\"\"{html}\"\"\""
+               tpl.addn "\t\tassert md_to_html(md) == html"
+               tpl.addn "\tend"
+               return tpl.write_to_string
+       end
+end
+
+if args.length != 2 then
+       print "Usage: commonmark_gen <tests.json> <output_dir>"
+       exit 1
+end
+
+var gen = new TestGenerator(args.first, args.last)
+gen.gen_tests
diff --git a/lib/markdown2/tests/test_commonmark_atx_headings.nit b/lib/markdown2/tests/test_commonmark_atx_headings.nit
new file mode 100644 (file)
index 0000000..749ab18
--- /dev/null
@@ -0,0 +1,130 @@
+# 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.
+
+module test_commonmark_atx_headings is test
+
+import test_markdown
+
+class TestCommonmarkATXHeadings
+       super TestMarkdownHtml
+       test
+
+       fun test32 is test do
+               var md = """# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n"""
+               var html = """<h1>foo</h1>\n<h2>foo</h2>\n<h3>foo</h3>\n<h4>foo</h4>\n<h5>foo</h5>\n<h6>foo</h6>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test33 is test do
+               var md = """####### foo\n"""
+               var html = """<p>####### foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test34 is test do
+               var md = """#5 bolt\n\n#hashtag\n"""
+               var html = """<p>#5 bolt</p>\n<p>#hashtag</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test35 is test do
+               var md = """\\## foo\n"""
+               var html = """<p>## foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test36 is test do
+               var md = """# foo *bar* \\*baz\\*\n"""
+               var html = """<h1>foo <em>bar</em> *baz*</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test37 is test do
+               var md = """#                  foo                     \n"""
+               var html = """<h1>foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test38 is test do
+               var md = """ ### foo\n  ## foo\n   # foo\n"""
+               var html = """<h3>foo</h3>\n<h2>foo</h2>\n<h1>foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test39 is test do
+               var md = """    # foo\n"""
+               var html = """<pre><code># foo\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test40 is test do
+               var md = """foo\n    # bar\n"""
+               var html = """<p>foo\n# bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test41 is test do
+               var md = """## foo ##\n  ###   bar    ###\n"""
+               var html = """<h2>foo</h2>\n<h3>bar</h3>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test42 is test do
+               var md = """# foo ##################################\n##### foo ##\n"""
+               var html = """<h1>foo</h1>\n<h5>foo</h5>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test43 is test do
+               var md = """### foo ###     \n"""
+               var html = """<h3>foo</h3>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test44 is test do
+               var md = """### foo ### b\n"""
+               var html = """<h3>foo ### b</h3>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test45 is test do
+               var md = """# foo#\n"""
+               var html = """<h1>foo#</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test46 is test do
+               var md = """### foo \\###\n## foo #\\##\n# foo \\#\n"""
+               var html = """<h3>foo ###</h3>\n<h2>foo ###</h2>\n<h1>foo #</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test47 is test do
+               var md = """****\n## foo\n****\n"""
+               var html = """<hr />\n<h2>foo</h2>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test48 is test do
+               var md = """Foo bar\n# baz\nBar foo\n"""
+               var html = """<p>Foo bar</p>\n<h1>baz</h1>\n<p>Bar foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test49 is test do
+               var md = """## \n#\n### ###\n"""
+               var html = """<h2></h2>\n<h1></h1>\n<h3></h3>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_autolinks.nit b/lib/markdown2/tests/test_commonmark_autolinks.nit
new file mode 100644 (file)
index 0000000..04c718c
--- /dev/null
@@ -0,0 +1,136 @@
+# 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.
+
+module test_commonmark_autolinks is test
+
+import test_markdown
+
+class TestCommonmarkAutolinks
+       super TestMarkdownHtml
+       test
+
+       fun test568 is test do
+               var md = """<http://foo.bar.baz>\n"""
+               var html = """<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test569 is test do
+               var md = """<http://foo.bar.baz/test?q=hello&id=22&boolean>\n"""
+               var html = """<p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test570 is test do
+               var md = """<irc://foo.bar:2233/baz>\n"""
+               var html = """<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test571 is test do
+               var md = """<MAILTO:FOO@BAR.BAZ>\n"""
+               var html = """<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test572 is test do
+               var md = """<a+b+c:d>\n"""
+               var html = """<p><a href="a+b+c:d">a+b+c:d</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test573 is test do
+               var md = """<made-up-scheme://foo,bar>\n"""
+               var html = """<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test574 is test do
+               var md = """<http://../>\n"""
+               var html = """<p><a href="http://../">http://../</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test575 is test do
+               var md = """<localhost:5001/foo>\n"""
+               var html = """<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test576 is test do
+               var md = """<http://foo.bar/baz bim>\n"""
+               var html = """<p>&lt;http://foo.bar/baz bim&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test577 is test do
+               var md = """<http://example.com/\\[\\>\n"""
+               var html = """<p><a href="http://example.com/%5C%5B%5C">http://example.com/\\[\\</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test578 is test do
+               var md = """<foo@bar.example.com>\n"""
+               var html = """<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test579 is test do
+               var md = """<foo+special@Bar.baz-bar0.com>\n"""
+               var html = """<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test580 is test do
+               var md = """<foo\\+@bar.example.com>\n"""
+               var html = """<p>&lt;foo+@bar.example.com&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test581 is test do
+               var md = """<>\n"""
+               var html = """<p>&lt;&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test582 is test do
+               var md = """< http://foo.bar >\n"""
+               var html = """<p>&lt; http://foo.bar &gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test583 is test do
+               var md = """<m:abc>\n"""
+               var html = """<p>&lt;m:abc&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test584 is test do
+               var md = """<foo.bar.baz>\n"""
+               var html = """<p>&lt;foo.bar.baz&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test585 is test do
+               var md = """http://example.com\n"""
+               var html = """<p>http://example.com</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test586 is test do
+               var md = """foo@bar.example.com\n"""
+               var html = """<p>foo@bar.example.com</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_backslash_escapes.nit b/lib/markdown2/tests/test_commonmark_backslash_escapes.nit
new file mode 100644 (file)
index 0000000..819158e
--- /dev/null
@@ -0,0 +1,100 @@
+# 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.
+
+module test_commonmark_backslash_escapes is test
+
+import test_markdown
+
+class TestCommonmarkBackslashEscapes
+       super TestMarkdownHtml
+       test
+
+       fun test291 is test do
+               var md = """\\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n"""
+               var html = """<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test292 is test do
+               var md = """\\\t\\A\\a\\ \\3\\φ\\«\n"""
+               var html = """<p>\\\t\\A\\a\\ \\3\\φ\\«</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test293 is test do
+               var md = """\\*not emphasized*\n\\<br/> not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url "not a reference"\n"""
+               var html = """<p>*not emphasized*\n&lt;br/&gt; not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url &quot;not a reference&quot;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test294 is test do
+               var md = """\\\\*emphasis*\n"""
+               var html = """<p>\\<em>emphasis</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test295 is test do
+               var md = """foo\\\nbar\n"""
+               var html = """<p>foo<br />\nbar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test296 is test do
+               var md = """`` \\[\\` ``\n"""
+               var html = """<p><code>\\[\\`</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test297 is test do
+               var md = """    \\[\\]\n"""
+               var html = """<pre><code>\\[\\]\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test298 is test do
+               var md = """~~~\n\\[\\]\n~~~\n"""
+               var html = """<pre><code>\\[\\]\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test299 is test do
+               var md = """<http://example.com?find=\\*>\n"""
+               var html = """<p><a href="http://example.com?find=%5C*">http://example.com?find=\\*</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test300 is test do
+               var md = """<a href="/bar\\/)">\n"""
+               var html = """<a href="/bar\\/)">\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test301 is test do
+               var md = """[foo](/bar\\* "ti\\*tle")\n"""
+               var html = """<p><a href="/bar*" title="ti*tle">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test302 is test do
+               var md = """[foo]\n\n[foo]: /bar\\* "ti\\*tle"\n"""
+               var html = """<p><a href="/bar*" title="ti*tle">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test303 is test do
+               var md = """``` foo\\+bar\nfoo\n```\n"""
+               var html = """<pre><code class="language-foo+bar">foo\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_blank_lines.nit b/lib/markdown2/tests/test_commonmark_blank_lines.nit
new file mode 100644 (file)
index 0000000..f294684
--- /dev/null
@@ -0,0 +1,28 @@
+# 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.
+
+module test_commonmark_blank_lines is test
+
+import test_markdown
+
+class TestCommonmarkBlankLines
+       super TestMarkdownHtml
+       test
+
+       fun test190 is test do
+               var md = """  \n\naaa\n  \n\n# aaa\n\n  \n"""
+               var html = """<p>aaa</p>\n<h1>aaa</h1>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_block_quotes.nit b/lib/markdown2/tests/test_commonmark_block_quotes.nit
new file mode 100644 (file)
index 0000000..db9542f
--- /dev/null
@@ -0,0 +1,172 @@
+# 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.
+
+module test_commonmark_block_quotes is test
+
+import test_markdown
+
+class TestCommonmarkBlockQuotes
+       super TestMarkdownHtml
+       test
+
+       fun test191 is test do
+               var md = """> # Foo\n> bar\n> baz\n"""
+               var html = """<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test192 is test do
+               var md = """># Foo\n>bar\n> baz\n"""
+               var html = """<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test193 is test do
+               var md = """   > # Foo\n   > bar\n > baz\n"""
+               var html = """<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test194 is test do
+               var md = """    > # Foo\n    > bar\n    > baz\n"""
+               var html = """<pre><code>&gt; # Foo\n&gt; bar\n&gt; baz\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test195 is test do
+               var md = """> # Foo\n> bar\nbaz\n"""
+               var html = """<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test196 is test do
+               var md = """> bar\nbaz\n> foo\n"""
+               var html = """<blockquote>\n<p>bar\nbaz\nfoo</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test197 is test do
+               var md = """> foo\n---\n"""
+               var html = """<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test198 is test do
+               var md = """> - foo\n- bar\n"""
+               var html = """<blockquote>\n<ul>\n<li>foo</li>\n</ul>\n</blockquote>\n<ul>\n<li>bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test199 is test do
+               var md = """>     foo\n    bar\n"""
+               var html = """<blockquote>\n<pre><code>foo\n</code></pre>\n</blockquote>\n<pre><code>bar\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test200 is test do
+               var md = """> ```\nfoo\n```\n"""
+               var html = """<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test201 is test do
+               var md = """> foo\n    - bar\n"""
+               var html = """<blockquote>\n<p>foo\n- bar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test202 is test do
+               var md = """>\n"""
+               var html = """<blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test203 is test do
+               var md = """>\n>  \n> \n"""
+               var html = """<blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test204 is test do
+               var md = """>\n> foo\n>  \n"""
+               var html = """<blockquote>\n<p>foo</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test205 is test do
+               var md = """> foo\n\n> bar\n"""
+               var html = """<blockquote>\n<p>foo</p>\n</blockquote>\n<blockquote>\n<p>bar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test206 is test do
+               var md = """> foo\n> bar\n"""
+               var html = """<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test207 is test do
+               var md = """> foo\n>\n> bar\n"""
+               var html = """<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test208 is test do
+               var md = """foo\n> bar\n"""
+               var html = """<p>foo</p>\n<blockquote>\n<p>bar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test209 is test do
+               var md = """> aaa\n***\n> bbb\n"""
+               var html = """<blockquote>\n<p>aaa</p>\n</blockquote>\n<hr />\n<blockquote>\n<p>bbb</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test210 is test do
+               var md = """> bar\nbaz\n"""
+               var html = """<blockquote>\n<p>bar\nbaz</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test211 is test do
+               var md = """> bar\n\nbaz\n"""
+               var html = """<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test212 is test do
+               var md = """> bar\n>\nbaz\n"""
+               var html = """<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test213 is test do
+               var md = """> > > foo\nbar\n"""
+               var html = """<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n</blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test214 is test do
+               var md = """>>> foo\n> bar\n>>baz\n"""
+               var html = """<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar\nbaz</p>\n</blockquote>\n</blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test215 is test do
+               var md = """>     code\n\n>    not code\n"""
+               var html = """<blockquote>\n<pre><code>code\n</code></pre>\n</blockquote>\n<blockquote>\n<p>not code</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_code_spans.nit b/lib/markdown2/tests/test_commonmark_code_spans.nit
new file mode 100644 (file)
index 0000000..edcf96b
--- /dev/null
@@ -0,0 +1,124 @@
+# 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.
+
+module test_commonmark_code_spans is test
+
+import test_markdown
+
+class TestCommonmarkCodeSpans
+       super TestMarkdownHtml
+       test
+
+       fun test316 is test do
+               var md = """`foo`\n"""
+               var html = """<p><code>foo</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test317 is test do
+               var md = """`` foo ` bar  ``\n"""
+               var html = """<p><code>foo ` bar</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test318 is test do
+               var md = """` `` `\n"""
+               var html = """<p><code>``</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test319 is test do
+               var md = """``\nfoo\n``\n"""
+               var html = """<p><code>foo</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test320 is test do
+               var md = """`foo   bar\n  baz`\n"""
+               var html = """<p><code>foo bar baz</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test321 is test do
+               var md = """`a  b`\n"""
+               var html = """<p><code>a  b</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test322 is test do
+               var md = """`foo `` bar`\n"""
+               var html = """<p><code>foo `` bar</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test323 is test do
+               var md = """`foo\\`bar`\n"""
+               var html = """<p><code>foo\\</code>bar`</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test324 is test do
+               var md = """*foo`*`\n"""
+               var html = """<p>*foo<code>*</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test325 is test do
+               var md = """[not a `link](/foo`)\n"""
+               var html = """<p>[not a <code>link](/foo</code>)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test326 is test do
+               var md = """`<a href="`">`\n"""
+               var html = """<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test327 is test do
+               var md = """<a href="`">`\n"""
+               var html = """<p><a href="`">`</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test328 is test do
+               var md = """`<http://foo.bar.`baz>`\n"""
+               var html = """<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test329 is test do
+               var md = """<http://foo.bar.`baz>`\n"""
+               var html = """<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test330 is test do
+               var md = """```foo``\n"""
+               var html = """<p>```foo``</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test331 is test do
+               var md = """`foo\n"""
+               var html = """<p>`foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test332 is test do
+               var md = """`foo``bar``\n"""
+               var html = """<p>`foo<code>bar</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_emphasis_and_strong_emphasis.nit b/lib/markdown2/tests/test_commonmark_emphasis_and_strong_emphasis.nit
new file mode 100644 (file)
index 0000000..64e317b
--- /dev/null
@@ -0,0 +1,796 @@
+# 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.
+
+module test_commonmark_emphasis_and_strong_emphasis is test
+
+import test_markdown
+
+class TestCommonmarkEmphasisAndStrongEmphasis
+       super TestMarkdownHtml
+       test
+
+       fun test333 is test do
+               var md = """*foo bar*\n"""
+               var html = """<p><em>foo bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test334 is test do
+               var md = """a * foo bar*\n"""
+               var html = """<p>a * foo bar*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test335 is test do
+               var md = """a*"foo"*\n"""
+               var html = """<p>a*&quot;foo&quot;*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test336 is test do
+               var md = """* a *\n"""
+               var html = """<p>* a *</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test337 is test do
+               var md = """foo*bar*\n"""
+               var html = """<p>foo<em>bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test338 is test do
+               var md = """5*6*78\n"""
+               var html = """<p>5<em>6</em>78</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test339 is test do
+               var md = """_foo bar_\n"""
+               var html = """<p><em>foo bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test340 is test do
+               var md = """_ foo bar_\n"""
+               var html = """<p>_ foo bar_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test341 is test do
+               var md = """a_"foo"_\n"""
+               var html = """<p>a_&quot;foo&quot;_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test342 is test do
+               var md = """foo_bar_\n"""
+               var html = """<p>foo_bar_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test343 is test do
+               var md = """5_6_78\n"""
+               var html = """<p>5_6_78</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test344 is test do
+               var md = """пристаням_стремятся_\n"""
+               var html = """<p>пристаням_стремятся_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test345 is test do
+               var md = """aa_"bb"_cc\n"""
+               var html = """<p>aa_&quot;bb&quot;_cc</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test346 is test do
+               var md = """foo-_(bar)_\n"""
+               var html = """<p>foo-<em>(bar)</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test347 is test do
+               var md = """_foo*\n"""
+               var html = """<p>_foo*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test348 is test do
+               var md = """*foo bar *\n"""
+               var html = """<p>*foo bar *</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test349 is test do
+               var md = """*foo bar\n*\n"""
+               var html = """<p>*foo bar\n*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test350 is test do
+               var md = """*(*foo)\n"""
+               var html = """<p>*(*foo)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test351 is test do
+               var md = """*(*foo*)*\n"""
+               var html = """<p><em>(<em>foo</em>)</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test352 is test do
+               var md = """*foo*bar\n"""
+               var html = """<p><em>foo</em>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test353 is test do
+               var md = """_foo bar _\n"""
+               var html = """<p>_foo bar _</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test354 is test do
+               var md = """_(_foo)\n"""
+               var html = """<p>_(_foo)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test355 is test do
+               var md = """_(_foo_)_\n"""
+               var html = """<p><em>(<em>foo</em>)</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test356 is test do
+               var md = """_foo_bar\n"""
+               var html = """<p>_foo_bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test357 is test do
+               var md = """_пристаням_стремятся\n"""
+               var html = """<p>_пристаням_стремятся</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test358 is test do
+               var md = """_foo_bar_baz_\n"""
+               var html = """<p><em>foo_bar_baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test359 is test do
+               var md = """_(bar)_.\n"""
+               var html = """<p><em>(bar)</em>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test360 is test do
+               var md = """**foo bar**\n"""
+               var html = """<p><strong>foo bar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test361 is test do
+               var md = """** foo bar**\n"""
+               var html = """<p>** foo bar**</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test362 is test do
+               var md = """a**"foo"**\n"""
+               var html = """<p>a**&quot;foo&quot;**</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test363 is test do
+               var md = """foo**bar**\n"""
+               var html = """<p>foo<strong>bar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test364 is test do
+               var md = """__foo bar__\n"""
+               var html = """<p><strong>foo bar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test365 is test do
+               var md = """__ foo bar__\n"""
+               var html = """<p>__ foo bar__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test366 is test do
+               var md = """__\nfoo bar__\n"""
+               var html = """<p>__\nfoo bar__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test367 is test do
+               var md = """a__"foo"__\n"""
+               var html = """<p>a__&quot;foo&quot;__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test368 is test do
+               var md = """foo__bar__\n"""
+               var html = """<p>foo__bar__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test369 is test do
+               var md = """5__6__78\n"""
+               var html = """<p>5__6__78</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test370 is test do
+               var md = """пристаням__стремятся__\n"""
+               var html = """<p>пристаням__стремятся__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test371 is test do
+               var md = """__foo, __bar__, baz__\n"""
+               var html = """<p><strong>foo, <strong>bar</strong>, baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test372 is test do
+               var md = """foo-__(bar)__\n"""
+               var html = """<p>foo-<strong>(bar)</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test373 is test do
+               var md = """**foo bar **\n"""
+               var html = """<p>**foo bar **</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test374 is test do
+               var md = """**(**foo)\n"""
+               var html = """<p>**(**foo)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test375 is test do
+               var md = """*(**foo**)*\n"""
+               var html = """<p><em>(<strong>foo</strong>)</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test376 is test do
+               var md = """**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**\n"""
+               var html = """<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.\n<em>Asclepias physocarpa</em>)</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test377 is test do
+               var md = """**foo "*bar*" foo**\n"""
+               var html = """<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test378 is test do
+               var md = """**foo**bar\n"""
+               var html = """<p><strong>foo</strong>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test379 is test do
+               var md = """__foo bar __\n"""
+               var html = """<p>__foo bar __</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test380 is test do
+               var md = """__(__foo)\n"""
+               var html = """<p>__(__foo)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test381 is test do
+               var md = """_(__foo__)_\n"""
+               var html = """<p><em>(<strong>foo</strong>)</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test382 is test do
+               var md = """__foo__bar\n"""
+               var html = """<p>__foo__bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test383 is test do
+               var md = """__пристаням__стремятся\n"""
+               var html = """<p>__пристаням__стремятся</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test384 is test do
+               var md = """__foo__bar__baz__\n"""
+               var html = """<p><strong>foo__bar__baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test385 is test do
+               var md = """__(bar)__.\n"""
+               var html = """<p><strong>(bar)</strong>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test386 is test do
+               var md = """*foo [bar](/url)*\n"""
+               var html = """<p><em>foo <a href="/url">bar</a></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test387 is test do
+               var md = """*foo\nbar*\n"""
+               var html = """<p><em>foo\nbar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test388 is test do
+               var md = """_foo __bar__ baz_\n"""
+               var html = """<p><em>foo <strong>bar</strong> baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test389 is test do
+               var md = """_foo _bar_ baz_\n"""
+               var html = """<p><em>foo <em>bar</em> baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test390 is test do
+               var md = """__foo_ bar_\n"""
+               var html = """<p><em><em>foo</em> bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test391 is test do
+               var md = """*foo *bar**\n"""
+               var html = """<p><em>foo <em>bar</em></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test392 is test do
+               var md = """*foo **bar** baz*\n"""
+               var html = """<p><em>foo <strong>bar</strong> baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test393 is test do
+               var md = """*foo**bar**baz*\n"""
+               var html = """<p><em>foo<strong>bar</strong>baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test394 is test do
+               var md = """*foo**bar*\n"""
+               var html = """<p><em>foo**bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test395 is test do
+               var md = """***foo** bar*\n"""
+               var html = """<p><em><strong>foo</strong> bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test396 is test do
+               var md = """*foo **bar***\n"""
+               var html = """<p><em>foo <strong>bar</strong></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test397 is test do
+               var md = """*foo**bar***\n"""
+               var html = """<p><em>foo<strong>bar</strong></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test398 is test do
+               var md = """*foo **bar *baz* bim** bop*\n"""
+               var html = """<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test399 is test do
+               var md = """*foo [*bar*](/url)*\n"""
+               var html = """<p><em>foo <a href="/url"><em>bar</em></a></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test400 is test do
+               var md = """** is not an empty emphasis\n"""
+               var html = """<p>** is not an empty emphasis</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test401 is test do
+               var md = """**** is not an empty strong emphasis\n"""
+               var html = """<p>**** is not an empty strong emphasis</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test402 is test do
+               var md = """**foo [bar](/url)**\n"""
+               var html = """<p><strong>foo <a href="/url">bar</a></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test403 is test do
+               var md = """**foo\nbar**\n"""
+               var html = """<p><strong>foo\nbar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test404 is test do
+               var md = """__foo _bar_ baz__\n"""
+               var html = """<p><strong>foo <em>bar</em> baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test405 is test do
+               var md = """__foo __bar__ baz__\n"""
+               var html = """<p><strong>foo <strong>bar</strong> baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test406 is test do
+               var md = """____foo__ bar__\n"""
+               var html = """<p><strong><strong>foo</strong> bar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test407 is test do
+               var md = """**foo **bar****\n"""
+               var html = """<p><strong>foo <strong>bar</strong></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test408 is test do
+               var md = """**foo *bar* baz**\n"""
+               var html = """<p><strong>foo <em>bar</em> baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test409 is test do
+               var md = """**foo*bar*baz**\n"""
+               var html = """<p><strong>foo<em>bar</em>baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test410 is test do
+               var md = """***foo* bar**\n"""
+               var html = """<p><strong><em>foo</em> bar</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test411 is test do
+               var md = """**foo *bar***\n"""
+               var html = """<p><strong>foo <em>bar</em></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test412 is test do
+               var md = """**foo *bar **baz**\nbim* bop**\n"""
+               var html = """<p><strong>foo <em>bar <strong>baz</strong>\nbim</em> bop</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test413 is test do
+               var md = """**foo [*bar*](/url)**\n"""
+               var html = """<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test414 is test do
+               var md = """__ is not an empty emphasis\n"""
+               var html = """<p>__ is not an empty emphasis</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test415 is test do
+               var md = """____ is not an empty strong emphasis\n"""
+               var html = """<p>____ is not an empty strong emphasis</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test416 is test do
+               var md = """foo ***\n"""
+               var html = """<p>foo ***</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test417 is test do
+               var md = """foo *\\**\n"""
+               var html = """<p>foo <em>*</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test418 is test do
+               var md = """foo *_*\n"""
+               var html = """<p>foo <em>_</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test419 is test do
+               var md = """foo *****\n"""
+               var html = """<p>foo *****</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test420 is test do
+               var md = """foo **\\***\n"""
+               var html = """<p>foo <strong>*</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test421 is test do
+               var md = """foo **_**\n"""
+               var html = """<p>foo <strong>_</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test422 is test do
+               var md = """**foo*\n"""
+               var html = """<p>*<em>foo</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test423 is test do
+               var md = """*foo**\n"""
+               var html = """<p><em>foo</em>*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test424 is test do
+               var md = """***foo**\n"""
+               var html = """<p>*<strong>foo</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test425 is test do
+               var md = """****foo*\n"""
+               var html = """<p>***<em>foo</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test426 is test do
+               var md = """**foo***\n"""
+               var html = """<p><strong>foo</strong>*</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test427 is test do
+               var md = """*foo****\n"""
+               var html = """<p><em>foo</em>***</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test428 is test do
+               var md = """foo ___\n"""
+               var html = """<p>foo ___</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test429 is test do
+               var md = """foo _\\__\n"""
+               var html = """<p>foo <em>_</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test430 is test do
+               var md = """foo _*_\n"""
+               var html = """<p>foo <em>*</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test431 is test do
+               var md = """foo _____\n"""
+               var html = """<p>foo _____</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test432 is test do
+               var md = """foo __\\___\n"""
+               var html = """<p>foo <strong>_</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test433 is test do
+               var md = """foo __*__\n"""
+               var html = """<p>foo <strong>*</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test434 is test do
+               var md = """__foo_\n"""
+               var html = """<p>_<em>foo</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test435 is test do
+               var md = """_foo__\n"""
+               var html = """<p><em>foo</em>_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test436 is test do
+               var md = """___foo__\n"""
+               var html = """<p>_<strong>foo</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test437 is test do
+               var md = """____foo_\n"""
+               var html = """<p>___<em>foo</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test438 is test do
+               var md = """__foo___\n"""
+               var html = """<p><strong>foo</strong>_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test439 is test do
+               var md = """_foo____\n"""
+               var html = """<p><em>foo</em>___</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test440 is test do
+               var md = """**foo**\n"""
+               var html = """<p><strong>foo</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test441 is test do
+               var md = """*_foo_*\n"""
+               var html = """<p><em><em>foo</em></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test442 is test do
+               var md = """__foo__\n"""
+               var html = """<p><strong>foo</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test443 is test do
+               var md = """_*foo*_\n"""
+               var html = """<p><em><em>foo</em></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test444 is test do
+               var md = """****foo****\n"""
+               var html = """<p><strong><strong>foo</strong></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test445 is test do
+               var md = """____foo____\n"""
+               var html = """<p><strong><strong>foo</strong></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test446 is test do
+               var md = """******foo******\n"""
+               var html = """<p><strong><strong><strong>foo</strong></strong></strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test447 is test do
+               var md = """***foo***\n"""
+               var html = """<p><em><strong>foo</strong></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test448 is test do
+               var md = """_____foo_____\n"""
+               var html = """<p><em><strong><strong>foo</strong></strong></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test449 is test do
+               var md = """*foo _bar* baz_\n"""
+               var html = """<p><em>foo _bar</em> baz_</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test450 is test do
+               var md = """*foo __bar *baz bim__ bam*\n"""
+               var html = """<p><em>foo <strong>bar *baz bim</strong> bam</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test451 is test do
+               var md = """**foo **bar baz**\n"""
+               var html = """<p>**foo <strong>bar baz</strong></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test452 is test do
+               var md = """*foo *bar baz*\n"""
+               var html = """<p>*foo <em>bar baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test453 is test do
+               var md = """*[bar*](/url)\n"""
+               var html = """<p>*<a href="/url">bar*</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test454 is test do
+               var md = """_foo [bar_](/url)\n"""
+               var html = """<p>_foo <a href="/url">bar_</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test455 is test do
+               var md = """*<img src="foo" title="*"/>\n"""
+               var html = """<p>*<img src="foo" title="*"/></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test456 is test do
+               var md = """**<a href="**">\n"""
+               var html = """<p>**<a href="**"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test457 is test do
+               var md = """__<a href="__">\n"""
+               var html = """<p>__<a href="__"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test458 is test do
+               var md = """*a `*`*\n"""
+               var html = """<p><em>a <code>*</code></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test459 is test do
+               var md = """_a `_`_\n"""
+               var html = """<p><em>a <code>_</code></em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test460 is test do
+               var md = """**a<http://foo.bar/?q=**>\n"""
+               var html = """<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test461 is test do
+               var md = """__a<http://foo.bar/?q=__>\n"""
+               var html = """<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_entity_and_numeric_character_references.nit b/lib/markdown2/tests/test_commonmark_entity_and_numeric_character_references.nit
new file mode 100644 (file)
index 0000000..f61edd4
--- /dev/null
@@ -0,0 +1,58 @@
+# 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.
+
+module test_commonmark_entity_and_numeric_character_references is test
+
+import test_markdown
+
+class TestCommonmarkEntityAndNumericCharacterReferences
+       super TestMarkdownHtml
+       test
+
+       fun test307 is test do
+               var md = """&nbsp &x; &#; &#x;\n&#987654321;\n&#abcdef0;\n&ThisIsNotDefined; &hi?;\n"""
+               var html = """<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;\n&amp;#987654321;\n&amp;#abcdef0;\n&amp;ThisIsNotDefined; &amp;hi?;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test308 is test do
+               var md = """&copy\n"""
+               var html = """<p>&amp;copy</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test309 is test do
+               var md = """&MadeUpEntity;\n"""
+               var html = """<p>&amp;MadeUpEntity;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test310 is test do
+               var md = """<a href="&ouml;&ouml;.html">\n"""
+               var html = """<a href="&ouml;&ouml;.html">\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test314 is test do
+               var md = """`f&ouml;&ouml;`\n"""
+               var html = """<p><code>f&amp;ouml;&amp;ouml;</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test315 is test do
+               var md = """    f&ouml;f&ouml;\n"""
+               var html = """<pre><code>f&amp;ouml;f&amp;ouml;\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_fenced_code_blocks.nit b/lib/markdown2/tests/test_commonmark_fenced_code_blocks.nit
new file mode 100644 (file)
index 0000000..2d7072a
--- /dev/null
@@ -0,0 +1,190 @@
+# 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.
+
+module test_commonmark_fenced_code_blocks is test
+
+import test_markdown
+
+class TestCommonmarkFencedCodeBlocks
+       super TestMarkdownHtml
+       test
+
+       fun test88 is test do
+               var md = """```\n<\n >\n```\n"""
+               var html = """<pre><code>&lt;\n &gt;\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test89 is test do
+               var md = """~~~\n<\n >\n~~~\n"""
+               var html = """<pre><code>&lt;\n &gt;\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test90 is test do
+               var md = """``\nfoo\n``\n"""
+               var html = """<p><code>foo</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test91 is test do
+               var md = """```\naaa\n~~~\n```\n"""
+               var html = """<pre><code>aaa\n~~~\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test92 is test do
+               var md = """~~~\naaa\n```\n~~~\n"""
+               var html = """<pre><code>aaa\n```\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test93 is test do
+               var md = """````\naaa\n```\n``````\n"""
+               var html = """<pre><code>aaa\n```\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test94 is test do
+               var md = """~~~~\naaa\n~~~\n~~~~\n"""
+               var html = """<pre><code>aaa\n~~~\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test95 is test do
+               var md = """```\n"""
+               var html = """<pre><code></code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test96 is test do
+               var md = """`````\n\n```\naaa\n"""
+               var html = """<pre><code>\n```\naaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test97 is test do
+               var md = """> ```\n> aaa\n\nbbb\n"""
+               var html = """<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test98 is test do
+               var md = """```\n\n  \n```\n"""
+               var html = """<pre><code>\n  \n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test99 is test do
+               var md = """```\n```\n"""
+               var html = """<pre><code></code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test100 is test do
+               var md = """ ```\n aaa\naaa\n```\n"""
+               var html = """<pre><code>aaa\naaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test101 is test do
+               var md = """  ```\naaa\n  aaa\naaa\n  ```\n"""
+               var html = """<pre><code>aaa\naaa\naaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test102 is test do
+               var md = """   ```\n   aaa\n    aaa\n  aaa\n   ```\n"""
+               var html = """<pre><code>aaa\n aaa\naaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test103 is test do
+               var md = """    ```\n    aaa\n    ```\n"""
+               var html = """<pre><code>```\naaa\n```\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test104 is test do
+               var md = """```\naaa\n  ```\n"""
+               var html = """<pre><code>aaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test105 is test do
+               var md = """   ```\naaa\n  ```\n"""
+               var html = """<pre><code>aaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test106 is test do
+               var md = """```\naaa\n    ```\n"""
+               var html = """<pre><code>aaa\n    ```\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test107 is test do
+               var md = """``` ```\naaa\n"""
+               var html = """<p><code></code>\naaa</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test108 is test do
+               var md = """~~~~~~\naaa\n~~~ ~~\n"""
+               var html = """<pre><code>aaa\n~~~ ~~\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test109 is test do
+               var md = """foo\n```\nbar\n```\nbaz\n"""
+               var html = """<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test110 is test do
+               var md = """foo\n---\n~~~\nbar\n~~~\n# baz\n"""
+               var html = """<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test111 is test do
+               var md = """```ruby\ndef foo(x)\n  return 3\nend\n```\n"""
+               var html = """<pre><code class="language-ruby">def foo(x)\n  return 3\nend\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test112 is test do
+               var md = """~~~~    ruby startline=3 $%@#$\ndef foo(x)\n  return 3\nend\n~~~~~~~\n"""
+               var html = """<pre><code class="language-ruby">def foo(x)\n  return 3\nend\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test113 is test do
+               var md = """````;\n````\n"""
+               var html = """<pre><code class="language-;"></code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test114 is test do
+               var md = """``` aa ```\nfoo\n"""
+               var html = """<p><code>aa</code>\nfoo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test115 is test do
+               var md = """```\n``` aaa\n```\n"""
+               var html = """<pre><code>``` aaa\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_hard_line_breaks.nit b/lib/markdown2/tests/test_commonmark_hard_line_breaks.nit
new file mode 100644 (file)
index 0000000..7e2336f
--- /dev/null
@@ -0,0 +1,112 @@
+# 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.
+
+module test_commonmark_hard_line_breaks is test
+
+import test_markdown
+
+class TestCommonmarkHardLineBreaks
+       super TestMarkdownHtml
+       test
+
+       fun test608 is test do
+               var md = """foo  \nbaz\n"""
+               var html = """<p>foo<br />\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test609 is test do
+               var md = """foo\\\nbaz\n"""
+               var html = """<p>foo<br />\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test610 is test do
+               var md = """foo       \nbaz\n"""
+               var html = """<p>foo<br />\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test611 is test do
+               var md = """foo  \n     bar\n"""
+               var html = """<p>foo<br />\nbar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test612 is test do
+               var md = """foo\\\n     bar\n"""
+               var html = """<p>foo<br />\nbar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test613 is test do
+               var md = """*foo  \nbar*\n"""
+               var html = """<p><em>foo<br />\nbar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test614 is test do
+               var md = """*foo\\\nbar*\n"""
+               var html = """<p><em>foo<br />\nbar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test615 is test do
+               var md = """`code  \nspan`\n"""
+               var html = """<p><code>code span</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test616 is test do
+               var md = """`code\\\nspan`\n"""
+               var html = """<p><code>code\\ span</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test617 is test do
+               var md = """<a href="foo  \nbar">\n"""
+               var html = """<p><a href="foo  \nbar"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test618 is test do
+               var md = """<a href="foo\\\nbar">\n"""
+               var html = """<p><a href="foo\\\nbar"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test619 is test do
+               var md = """foo\\\n"""
+               var html = """<p>foo\\</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test620 is test do
+               var md = """foo  \n"""
+               var html = """<p>foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test621 is test do
+               var md = """### foo\\\n"""
+               var html = """<h3>foo\\</h3>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test622 is test do
+               var md = """### foo  \n"""
+               var html = """<h3>foo</h3>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_html_blocks.nit b/lib/markdown2/tests/test_commonmark_html_blocks.nit
new file mode 100644 (file)
index 0000000..5b92555
--- /dev/null
@@ -0,0 +1,280 @@
+# 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.
+
+module test_commonmark_html_blocks is test
+
+import test_markdown
+
+class TestCommonmarkHTMLBlocks
+       super TestMarkdownHtml
+       test
+
+       fun test116 is test do
+               var md = """<table><tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr></table>\n"""
+               var html = """<table><tr><td>\n<pre>\n**Hello**,\n<p><em>world</em>.\n</pre></p>\n</td></tr></table>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test117 is test do
+               var md = """<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n\nokay.\n"""
+               var html = """<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n<p>okay.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test118 is test do
+               var md = """ <div>\n  *hello*\n         <foo><a>\n"""
+               var html = """ <div>\n  *hello*\n         <foo><a>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test119 is test do
+               var md = """</div>\n*foo*\n"""
+               var html = """</div>\n*foo*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test120 is test do
+               var md = """<DIV CLASS="foo">\n\n*Markdown*\n\n</DIV>\n"""
+               var html = """<DIV CLASS="foo">\n<p><em>Markdown</em></p>\n</DIV>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test121 is test do
+               var md = """<div id="foo"\n  class="bar">\n</div>\n"""
+               var html = """<div id="foo"\n  class="bar">\n</div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test122 is test do
+               var md = """<div id="foo" class="bar\n  baz">\n</div>\n"""
+               var html = """<div id="foo" class="bar\n  baz">\n</div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test123 is test do
+               var md = """<div>\n*foo*\n\n*bar*\n"""
+               var html = """<div>\n*foo*\n<p><em>bar</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test124 is test do
+               var md = """<div id="foo"\n*hi*\n"""
+               var html = """<div id="foo"\n*hi*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test125 is test do
+               var md = """<div class\nfoo\n"""
+               var html = """<div class\nfoo\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test126 is test do
+               var md = """<div *???-&&&-<---\n*foo*\n"""
+               var html = """<div *???-&&&-<---\n*foo*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test127 is test do
+               var md = """<div><a href="bar">*foo*</a></div>\n"""
+               var html = """<div><a href="bar">*foo*</a></div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test128 is test do
+               var md = """<table><tr><td>\nfoo\n</td></tr></table>\n"""
+               var html = """<table><tr><td>\nfoo\n</td></tr></table>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test129 is test do
+               var md = """<div></div>\n``` c\nint x = 33;\n```\n"""
+               var html = """<div></div>\n``` c\nint x = 33;\n```\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test130 is test do
+               var md = """<a href="foo">\n*bar*\n</a>\n"""
+               var html = """<a href="foo">\n*bar*\n</a>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test131 is test do
+               var md = """<Warning>\n*bar*\n</Warning>\n"""
+               var html = """<Warning>\n*bar*\n</Warning>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test132 is test do
+               var md = """<i class="foo">\n*bar*\n</i>\n"""
+               var html = """<i class="foo">\n*bar*\n</i>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test133 is test do
+               var md = """</ins>\n*bar*\n"""
+               var html = """</ins>\n*bar*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test134 is test do
+               var md = """<del>\n*foo*\n</del>\n"""
+               var html = """<del>\n*foo*\n</del>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test135 is test do
+               var md = """<del>\n\n*foo*\n\n</del>\n"""
+               var html = """<del>\n<p><em>foo</em></p>\n</del>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test136 is test do
+               var md = """<del>*foo*</del>\n"""
+               var html = """<p><del><em>foo</em></del></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test137 is test do
+               var md = """<pre language="haskell"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay\n"""
+               var html = """<pre language="haskell"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test138 is test do
+               var md = """<script type="text/javascript">\n// JavaScript example\n\ndocument.getElementById("demo").innerHTML = "Hello JavaScript!";\n</script>\nokay\n"""
+               var html = """<script type="text/javascript">\n// JavaScript example\n\ndocument.getElementById("demo").innerHTML = "Hello JavaScript!";\n</script>\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test139 is test do
+               var md = """<style\n  type="text/css">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay\n"""
+               var html = """<style\n  type="text/css">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test140 is test do
+               var md = """<style\n  type="text/css">\n\nfoo\n"""
+               var html = """<style\n  type="text/css">\n\nfoo\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test141 is test do
+               var md = """> <div>\n> foo\n\nbar\n"""
+               var html = """<blockquote>\n<div>\nfoo\n</blockquote>\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test142 is test do
+               var md = """- <div>\n- foo\n"""
+               var html = """<ul>\n<li>\n<div>\n</li>\n<li>foo</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test143 is test do
+               var md = """<style>p{color:red;}</style>\n*foo*\n"""
+               var html = """<style>p{color:red;}</style>\n<p><em>foo</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test144 is test do
+               var md = """<!-- foo -->*bar*\n*baz*\n"""
+               var html = """<!-- foo -->*bar*\n<p><em>baz</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test145 is test do
+               var md = """<script>\nfoo\n</script>1. *bar*\n"""
+               var html = """<script>\nfoo\n</script>1. *bar*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test146 is test do
+               var md = """<!-- Foo\n\nbar\n   baz -->\nokay\n"""
+               var html = """<!-- Foo\n\nbar\n   baz -->\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test147 is test do
+               var md = """<?php\n\n  echo '>';\n\n?>\nokay\n"""
+               var html = """<?php\n\n  echo '>';\n\n?>\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test148 is test do
+               var md = """<!DOCTYPE html>\n"""
+               var html = """<!DOCTYPE html>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test149 is test do
+               var md = """<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\nokay\n"""
+               var html = """<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\n<p>okay</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test150 is test do
+               var md = """  <!-- foo -->\n\n    <!-- foo -->\n"""
+               var html = """  <!-- foo -->\n<pre><code>&lt;!-- foo --&gt;\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test151 is test do
+               var md = """  <div>\n\n    <div>\n"""
+               var html = """  <div>\n<pre><code>&lt;div&gt;\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test152 is test do
+               var md = """Foo\n<div>\nbar\n</div>\n"""
+               var html = """<p>Foo</p>\n<div>\nbar\n</div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test153 is test do
+               var md = """<div>\nbar\n</div>\n*foo*\n"""
+               var html = """<div>\nbar\n</div>\n*foo*\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test154 is test do
+               var md = """Foo\n<a href="bar">\nbaz\n"""
+               var html = """<p>Foo\n<a href="bar">\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test155 is test do
+               var md = """<div>\n\n*Emphasized* text.\n\n</div>\n"""
+               var html = """<div>\n<p><em>Emphasized</em> text.</p>\n</div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test156 is test do
+               var md = """<div>\n*Emphasized* text.\n</div>\n"""
+               var html = """<div>\n*Emphasized* text.\n</div>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test157 is test do
+               var md = """<table>\n\n<tr>\n\n<td>\nHi\n</td>\n\n</tr>\n\n</table>\n"""
+               var html = """<table>\n<tr>\n<td>\nHi\n</td>\n</tr>\n</table>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test158 is test do
+               var md = """<table>\n\n  <tr>\n\n    <td>\n      Hi\n    </td>\n\n  </tr>\n\n</table>\n"""
+               var html = """<table>\n  <tr>\n<pre><code>&lt;td&gt;\n  Hi\n&lt;/td&gt;\n</code></pre>\n  </tr>\n</table>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_images.nit b/lib/markdown2/tests/test_commonmark_images.nit
new file mode 100644 (file)
index 0000000..e75f4c1
--- /dev/null
@@ -0,0 +1,154 @@
+# 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.
+
+module test_commonmark_images is test
+
+import test_markdown
+
+class TestCommonmarkImages
+       super TestMarkdownHtml
+       test
+
+       fun test546 is test do
+               var md = """![foo](/url "title")\n"""
+               var html = """<p><img src="/url" alt="foo" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test547 is test do
+               var md = """![foo *bar*]\n\n[foo *bar*]: train.jpg "train & tracks"\n"""
+               var html = """<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test548 is test do
+               var md = """![foo ![bar](/url)](/url2)\n"""
+               var html = """<p><img src="/url2" alt="foo bar" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test549 is test do
+               var md = """![foo [bar](/url)](/url2)\n"""
+               var html = """<p><img src="/url2" alt="foo bar" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test550 is test do
+               var md = """![foo *bar*][]\n\n[foo *bar*]: train.jpg "train & tracks"\n"""
+               var html = """<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test551 is test do
+               var md = """![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg "train & tracks"\n"""
+               var html = """<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test552 is test do
+               var md = """![foo](train.jpg)\n"""
+               var html = """<p><img src="train.jpg" alt="foo" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test553 is test do
+               var md = """My ![foo bar](/path/to/train.jpg  "title"   )\n"""
+               var html = """<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test554 is test do
+               var md = """![foo](<url>)\n"""
+               var html = """<p><img src="url" alt="foo" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test555 is test do
+               var md = """![](/url)\n"""
+               var html = """<p><img src="/url" alt="" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test556 is test do
+               var md = """![foo][bar]\n\n[bar]: /url\n"""
+               var html = """<p><img src="/url" alt="foo" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test557 is test do
+               var md = """![foo][bar]\n\n[BAR]: /url\n"""
+               var html = """<p><img src="/url" alt="foo" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test558 is test do
+               var md = """![foo][]\n\n[foo]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="foo" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test559 is test do
+               var md = """![*foo* bar][]\n\n[*foo* bar]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="foo bar" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test560 is test do
+               var md = """![Foo][]\n\n[foo]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="Foo" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test561 is test do
+               var md = """![foo] \n[]\n\n[foo]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="foo" title="title" />\n[]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test562 is test do
+               var md = """![foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="foo" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test563 is test do
+               var md = """![*foo* bar]\n\n[*foo* bar]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="foo bar" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test564 is test do
+               var md = """![[foo]]\n\n[[foo]]: /url "title"\n"""
+               var html = """<p>![[foo]]</p>\n<p>[[foo]]: /url &quot;title&quot;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test565 is test do
+               var md = """![Foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p><img src="/url" alt="Foo" title="title" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test566 is test do
+               var md = """!\\[foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p>![foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test567 is test do
+               var md = """\\![foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p>!<a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_indented_code_blocks.nit b/lib/markdown2/tests/test_commonmark_indented_code_blocks.nit
new file mode 100644 (file)
index 0000000..0c8bf2f
--- /dev/null
@@ -0,0 +1,94 @@
+# 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.
+
+module test_commonmark_indented_code_blocks is test
+
+import test_markdown
+
+class TestCommonmarkIndentedCodeBlocks
+       super TestMarkdownHtml
+       test
+
+       fun test76 is test do
+               var md = """    a simple\n      indented code block\n"""
+               var html = """<pre><code>a simple\n  indented code block\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test77 is test do
+               var md = """  - foo\n\n    bar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test78 is test do
+               var md = """1.  foo\n\n    - bar\n"""
+               var html = """<ol>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test79 is test do
+               var md = """    <a/>\n    *hi*\n\n    - one\n"""
+               var html = """<pre><code>&lt;a/&gt;\n*hi*\n\n- one\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test80 is test do
+               var md = """    chunk1\n\n    chunk2\n  \n \n \n    chunk3\n"""
+               var html = """<pre><code>chunk1\n\nchunk2\n\n\n\nchunk3\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test81 is test do
+               var md = """    chunk1\n      \n      chunk2\n"""
+               var html = """<pre><code>chunk1\n  \n  chunk2\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test82 is test do
+               var md = """Foo\n    bar\n\n"""
+               var html = """<p>Foo\nbar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test83 is test do
+               var md = """    foo\nbar\n"""
+               var html = """<pre><code>foo\n</code></pre>\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test84 is test do
+               var md = """# Heading\n    foo\nHeading\n------\n    foo\n----\n"""
+               var html = """<h1>Heading</h1>\n<pre><code>foo\n</code></pre>\n<h2>Heading</h2>\n<pre><code>foo\n</code></pre>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test85 is test do
+               var md = """        foo\n    bar\n"""
+               var html = """<pre><code>    foo\nbar\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test86 is test do
+               var md = """\n    \n    foo\n    \n\n"""
+               var html = """<pre><code>foo\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test87 is test do
+               var md = """    foo  \n"""
+               var html = """<pre><code>foo  \n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_inlines.nit b/lib/markdown2/tests/test_commonmark_inlines.nit
new file mode 100644 (file)
index 0000000..ac13156
--- /dev/null
@@ -0,0 +1,28 @@
+# 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.
+
+module test_commonmark_inlines is test
+
+import test_markdown
+
+class TestCommonmarkInlines
+       super TestMarkdownHtml
+       test
+
+       fun test290 is test do
+               var md = """`hi`lo`\n"""
+               var html = """<p><code>hi</code>lo`</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_link_reference_definitions.nit b/lib/markdown2/tests/test_commonmark_link_reference_definitions.nit
new file mode 100644 (file)
index 0000000..ebd19a4
--- /dev/null
@@ -0,0 +1,154 @@
+# 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.
+
+module test_commonmark_link_reference_definitions is test
+
+import test_markdown
+
+class TestCommonmarkLinkReferenceDefinitions
+       super TestMarkdownHtml
+       test
+
+       fun test159 is test do
+               var md = """[foo]: /url "title"\n\n[foo]\n"""
+               var html = """<p><a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test160 is test do
+               var md = """   [foo]: \n      /url  \n           'the title'  \n\n[foo]\n"""
+               var html = """<p><a href="/url" title="the title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test161 is test do
+               var md = """[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]\n"""
+               var html = """<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test162 is test do
+               var md = """[Foo bar]:\n<my%20url>\n'title'\n\n[Foo bar]\n"""
+               var html = """<p><a href="my%20url" title="title">Foo bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test163 is test do
+               var md = """[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]\n"""
+               var html = """<p><a href="/url" title="\ntitle\nline1\nline2\n">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test164 is test do
+               var md = """[foo]: /url 'title\n\nwith blank line'\n\n[foo]\n"""
+               var html = """<p>[foo]: /url 'title</p>\n<p>with blank line'</p>\n<p>[foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test165 is test do
+               var md = """[foo]:\n/url\n\n[foo]\n"""
+               var html = """<p><a href="/url">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test166 is test do
+               var md = """[foo]:\n\n[foo]\n"""
+               var html = """<p>[foo]:</p>\n<p>[foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test167 is test do
+               var md = """[foo]: /url\\bar\\*baz "foo\\"bar\\baz"\n\n[foo]\n"""
+               var html = """<p><a href="/url%5Cbar*baz" title="foo&quot;bar\\baz">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test168 is test do
+               var md = """[foo]\n\n[foo]: url\n"""
+               var html = """<p><a href="url">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test169 is test do
+               var md = """[foo]\n\n[foo]: first\n[foo]: second\n"""
+               var html = """<p><a href="first">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test170 is test do
+               var md = """[FOO]: /url\n\n[Foo]\n"""
+               var html = """<p><a href="/url">Foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test172 is test do
+               var md = """[foo]: /url\n"""
+               var html = """"""
+               assert md_to_html(md) == html
+       end
+
+       fun test173 is test do
+               var md = """[\nfoo\n]: /url\nbar\n"""
+               var html = """<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test174 is test do
+               var md = """[foo]: /url "title" ok\n"""
+               var html = """<p>[foo]: /url &quot;title&quot; ok</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test175 is test do
+               var md = """[foo]: /url\n"title" ok\n"""
+               var html = """<p>&quot;title&quot; ok</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test176 is test do
+               var md = """    [foo]: /url "title"\n\n[foo]\n"""
+               var html = """<pre><code>[foo]: /url &quot;title&quot;\n</code></pre>\n<p>[foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test177 is test do
+               var md = """```\n[foo]: /url\n```\n\n[foo]\n"""
+               var html = """<pre><code>[foo]: /url\n</code></pre>\n<p>[foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test178 is test do
+               var md = """Foo\n[bar]: /baz\n\n[bar]\n"""
+               var html = """<p>Foo\n[bar]: /baz</p>\n<p>[bar]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test179 is test do
+               var md = """# [Foo]\n[foo]: /url\n> bar\n"""
+               var html = """<h1><a href="/url">Foo</a></h1>\n<blockquote>\n<p>bar</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test180 is test do
+               var md = """[foo]: /foo-url "foo"\n[bar]: /bar-url\n  "bar"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]\n"""
+               var html = """<p><a href="/foo-url" title="foo">foo</a>,\n<a href="/bar-url" title="bar">bar</a>,\n<a href="/baz-url">baz</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test181 is test do
+               var md = """[foo]\n\n> [foo]: /url\n"""
+               var html = """<p><a href="/url">foo</a></p>\n<blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_links.nit b/lib/markdown2/tests/test_commonmark_links.nit
new file mode 100644 (file)
index 0000000..bedbbbd
--- /dev/null
@@ -0,0 +1,514 @@
+# 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.
+
+module test_commonmark_links is test
+
+import test_markdown
+
+class TestCommonmarkLinks
+       super TestMarkdownHtml
+       test
+
+       fun test462 is test do
+               var md = """[link](/uri "title")\n"""
+               var html = """<p><a href="/uri" title="title">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test463 is test do
+               var md = """[link](/uri)\n"""
+               var html = """<p><a href="/uri">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test464 is test do
+               var md = """[link]()\n"""
+               var html = """<p><a href="">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test465 is test do
+               var md = """[link](<>)\n"""
+               var html = """<p><a href="">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test466 is test do
+               var md = """[link](/my uri)\n"""
+               var html = """<p>[link](/my uri)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test467 is test do
+               var md = """[link](</my%20uri>)\n"""
+               var html = """<p><a href="/my%20uri">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test468 is test do
+               var md = """[link](foo\nbar)\n"""
+               var html = """<p>[link](foo\nbar)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test469 is test do
+               var md = """[link](<foo\nbar>)\n"""
+               var html = """<p>[link](<foo\nbar>)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test470 is test do
+               var md = """[link](\\(foo\\))\n"""
+               var html = """<p><a href="(foo)">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test471 is test do
+               var md = """[link](foo(and(bar)))\n"""
+               var html = """<p><a href="foo(and(bar))">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test472 is test do
+               var md = """[link](foo\\(and\\(bar\\))\n"""
+               var html = """<p><a href="foo(and(bar)">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test473 is test do
+               var md = """[link](<foo(and(bar)>)\n"""
+               var html = """<p><a href="foo(and(bar)">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test474 is test do
+               var md = """[link](foo\\)\\:)\n"""
+               var html = """<p><a href="foo):">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test475 is test do
+               var md = """[link](#fragment)\n\n[link](http://example.com#fragment)\n\n[link](http://example.com?foo=3#frag)\n"""
+               var html = """<p><a href="#fragment">link</a></p>\n<p><a href="http://example.com#fragment">link</a></p>\n<p><a href="http://example.com?foo=3#frag">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test476 is test do
+               var md = """[link](foo\\bar)\n"""
+               var html = """<p><a href="foo%5Cbar">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test478 is test do
+               var md = """[link]("title")\n"""
+               var html = """<p><a href="%22title%22">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test479 is test do
+               var md = """[link](/url "title")\n[link](/url 'title')\n[link](/url (title))\n"""
+               var html = """<p><a href="/url" title="title">link</a>\n<a href="/url" title="title">link</a>\n<a href="/url" title="title">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test480 is test do
+               var md = """[link](/url "title \\"&quot;")\n"""
+               var html = """<p><a href="/url" title="title &quot;&quot;">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test481 is test do
+               var md = """[link](/url "title")\n"""
+               var html = """<p><a href="/url%C2%A0%22title%22">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test482 is test do
+               var md = """[link](/url "title "and" title")\n"""
+               var html = """<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test483 is test do
+               var md = """[link](/url 'title "and" title')\n"""
+               var html = """<p><a href="/url" title="title &quot;and&quot; title">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test484 is test do
+               var md = """[link](   /uri\n  "title"  )\n"""
+               var html = """<p><a href="/uri" title="title">link</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test485 is test do
+               var md = """[link] (/uri)\n"""
+               var html = """<p>[link] (/uri)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test486 is test do
+               var md = """[link [foo [bar]]](/uri)\n"""
+               var html = """<p><a href="/uri">link [foo [bar]]</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test487 is test do
+               var md = """[link] bar](/uri)\n"""
+               var html = """<p>[link] bar](/uri)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test488 is test do
+               var md = """[link [bar](/uri)\n"""
+               var html = """<p>[link <a href="/uri">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test489 is test do
+               var md = """[link \\[bar](/uri)\n"""
+               var html = """<p><a href="/uri">link [bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test490 is test do
+               var md = """[link *foo **bar** `#`*](/uri)\n"""
+               var html = """<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test491 is test do
+               var md = """[![moon](moon.jpg)](/uri)\n"""
+               var html = """<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test492 is test do
+               var md = """[foo [bar](/uri)](/uri)\n"""
+               var html = """<p>[foo <a href="/uri">bar</a>](/uri)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test493 is test do
+               var md = """[foo *[bar [baz](/uri)](/uri)*](/uri)\n"""
+               var html = """<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test494 is test do
+               var md = """![[[foo](uri1)](uri2)](uri3)\n"""
+               var html = """<p><img src="uri3" alt="[foo](uri2)" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test495 is test do
+               var md = """*[foo*](/uri)\n"""
+               var html = """<p>*<a href="/uri">foo*</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test496 is test do
+               var md = """[foo *bar](baz*)\n"""
+               var html = """<p><a href="baz*">foo *bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test497 is test do
+               var md = """*foo [bar* baz]\n"""
+               var html = """<p><em>foo [bar</em> baz]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test498 is test do
+               var md = """[foo <bar attr="](baz)">\n"""
+               var html = """<p>[foo <bar attr="](baz)"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test499 is test do
+               var md = """[foo`](/uri)`\n"""
+               var html = """<p>[foo<code>](/uri)</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test500 is test do
+               var md = """[foo<http://example.com/?search=](uri)>\n"""
+               var html = """<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test501 is test do
+               var md = """[foo][bar]\n\n[bar]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test502 is test do
+               var md = """[link [foo [bar]]][ref]\n\n[ref]: /uri\n"""
+               var html = """<p><a href="/uri">link [foo [bar]]</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test503 is test do
+               var md = """[link \\[bar][ref]\n\n[ref]: /uri\n"""
+               var html = """<p><a href="/uri">link [bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test504 is test do
+               var md = """[link *foo **bar** `#`*][ref]\n\n[ref]: /uri\n"""
+               var html = """<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test505 is test do
+               var md = """[![moon](moon.jpg)][ref]\n\n[ref]: /uri\n"""
+               var html = """<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test506 is test do
+               var md = """[foo [bar](/uri)][ref]\n\n[ref]: /uri\n"""
+               var html = """<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test507 is test do
+               var md = """[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri\n"""
+               var html = """<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test508 is test do
+               var md = """*[foo*][ref]\n\n[ref]: /uri\n"""
+               var html = """<p>*<a href="/uri">foo*</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test509 is test do
+               var md = """[foo *bar][ref]\n\n[ref]: /uri\n"""
+               var html = """<p><a href="/uri">foo *bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test510 is test do
+               var md = """[foo <bar attr="][ref]">\n\n[ref]: /uri\n"""
+               var html = """<p>[foo <bar attr="][ref]"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test511 is test do
+               var md = """[foo`][ref]`\n\n[ref]: /uri\n"""
+               var html = """<p>[foo<code>][ref]</code></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test512 is test do
+               var md = """[foo<http://example.com/?search=][ref]>\n\n[ref]: /uri\n"""
+               var html = """<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test513 is test do
+               var md = """[foo][BaR]\n\n[bar]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test515 is test do
+               var md = """[Foo\n  bar]: /url\n\n[Baz][Foo bar]\n"""
+               var html = """<p><a href="/url">Baz</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test516 is test do
+               var md = """[foo] [bar]\n\n[bar]: /url "title"\n"""
+               var html = """<p>[foo] <a href="/url" title="title">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test517 is test do
+               var md = """[foo]\n[bar]\n\n[bar]: /url "title"\n"""
+               var html = """<p>[foo]\n<a href="/url" title="title">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test518 is test do
+               var md = """[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]\n"""
+               var html = """<p><a href="/url1">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test519 is test do
+               var md = """[bar][foo\\!]\n\n[foo!]: /url\n"""
+               var html = """<p>[bar][foo!]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test520 is test do
+               var md = """[foo][ref[]\n\n[ref[]: /uri\n"""
+               var html = """<p>[foo][ref[]</p>\n<p>[ref[]: /uri</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test521 is test do
+               var md = """[foo][ref[bar]]\n\n[ref[bar]]: /uri\n"""
+               var html = """<p>[foo][ref[bar]]</p>\n<p>[ref[bar]]: /uri</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test522 is test do
+               var md = """[[[foo]]]\n\n[[[foo]]]: /url\n"""
+               var html = """<p>[[[foo]]]</p>\n<p>[[[foo]]]: /url</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test523 is test do
+               var md = """[foo][ref\\[]\n\n[ref\\[]: /uri\n"""
+               var html = """<p><a href="/uri">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test524 is test do
+               var md = """[bar\\\\]: /uri\n\n[bar\\\\]\n"""
+               var html = """<p><a href="/uri">bar\\</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test525 is test do
+               var md = """[]\n\n[]: /uri\n"""
+               var html = """<p>[]</p>\n<p>[]: /uri</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test526 is test do
+               var md = """[\n ]\n\n[\n ]: /uri\n"""
+               var html = """<p>[\n]</p>\n<p>[\n]: /uri</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test527 is test do
+               var md = """[foo][]\n\n[foo]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test528 is test do
+               var md = """[*foo* bar][]\n\n[*foo* bar]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title"><em>foo</em> bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test529 is test do
+               var md = """[Foo][]\n\n[foo]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">Foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test530 is test do
+               var md = """[foo] \n[]\n\n[foo]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">foo</a>\n[]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test531 is test do
+               var md = """[foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test532 is test do
+               var md = """[*foo* bar]\n\n[*foo* bar]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title"><em>foo</em> bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test533 is test do
+               var md = """[[*foo* bar]]\n\n[*foo* bar]: /url "title"\n"""
+               var html = """<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test534 is test do
+               var md = """[[bar [foo]\n\n[foo]: /url\n"""
+               var html = """<p>[[bar <a href="/url">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test535 is test do
+               var md = """[Foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p><a href="/url" title="title">Foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test536 is test do
+               var md = """[foo] bar\n\n[foo]: /url\n"""
+               var html = """<p><a href="/url">foo</a> bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test537 is test do
+               var md = """\\[foo]\n\n[foo]: /url "title"\n"""
+               var html = """<p>[foo]</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test538 is test do
+               var md = """[foo*]: /url\n\n*[foo*]\n"""
+               var html = """<p>*<a href="/url">foo*</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test539 is test do
+               var md = """[foo][bar]\n\n[foo]: /url1\n[bar]: /url2\n"""
+               var html = """<p><a href="/url2">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test540 is test do
+               var md = """[foo][]\n\n[foo]: /url1\n"""
+               var html = """<p><a href="/url1">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test541 is test do
+               var md = """[foo]()\n\n[foo]: /url1\n"""
+               var html = """<p><a href="">foo</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test542 is test do
+               var md = """[foo](not a link)\n\n[foo]: /url1\n"""
+               var html = """<p><a href="/url1">foo</a>(not a link)</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test543 is test do
+               var md = """[foo][bar][baz]\n\n[baz]: /url\n"""
+               var html = """<p>[foo]<a href="/url">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test544 is test do
+               var md = """[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2\n"""
+               var html = """<p><a href="/url2">foo</a><a href="/url1">baz</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test545 is test do
+               var md = """[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2\n"""
+               var html = """<p>[foo]<a href="/url1">bar</a></p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_list_items.nit b/lib/markdown2/tests/test_commonmark_list_items.nit
new file mode 100644 (file)
index 0000000..b4896ed
--- /dev/null
@@ -0,0 +1,310 @@
+# 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.
+
+module test_commonmark_list_items is test
+
+import test_markdown
+
+class TestCommonmarkListItems
+       super TestMarkdownHtml
+       test
+
+       fun test216 is test do
+               var md = """A paragraph\nwith two lines.\n\n    indented code\n\n> A block quote.\n"""
+               var html = """<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test217 is test do
+               var md = """1.  A paragraph\n    with two lines.\n\n        indented code\n\n    > A block quote.\n"""
+               var html = """<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test218 is test do
+               var md = """- one\n\n two\n"""
+               var html = """<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test219 is test do
+               var md = """- one\n\n  two\n"""
+               var html = """<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test220 is test do
+               var md = """ -    one\n\n     two\n"""
+               var html = """<ul>\n<li>one</li>\n</ul>\n<pre><code> two\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test221 is test do
+               var md = """ -    one\n\n      two\n"""
+               var html = """<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test222 is test do
+               var md = """   > > 1.  one\n>>\n>>     two\n"""
+               var html = """<blockquote>\n<blockquote>\n<ol>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ol>\n</blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test223 is test do
+               var md = """>>- one\n>>\n  >  > two\n"""
+               var html = """<blockquote>\n<blockquote>\n<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n</blockquote>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test224 is test do
+               var md = """-one\n\n2.two\n"""
+               var html = """<p>-one</p>\n<p>2.two</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test225 is test do
+               var md = """- foo\n\n\n  bar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test226 is test do
+               var md = """1.  foo\n\n    ```\n    bar\n    ```\n\n    baz\n\n    > bam\n"""
+               var html = """<ol>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n<blockquote>\n<p>bam</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test227 is test do
+               var md = """- Foo\n\n      bar\n\n\n      baz\n"""
+               var html = """<ul>\n<li>\n<p>Foo</p>\n<pre><code>bar\n\n\nbaz\n</code></pre>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test228 is test do
+               var md = """123456789. ok\n"""
+               var html = """<ol start="123456789">\n<li>ok</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test229 is test do
+               var md = """1234567890. not ok\n"""
+               var html = """<p>1234567890. not ok</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test230 is test do
+               var md = """0. ok\n"""
+               var html = """<ol start="0">\n<li>ok</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test231 is test do
+               var md = """003. ok\n"""
+               var html = """<ol start="3">\n<li>ok</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test232 is test do
+               var md = """-1. not ok\n"""
+               var html = """<p>-1. not ok</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test233 is test do
+               var md = """- foo\n\n      bar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test234 is test do
+               var md = """  10.  foo\n\n           bar\n"""
+               var html = """<ol start="10">\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test235 is test do
+               var md = """    indented code\n\nparagraph\n\n    more code\n"""
+               var html = """<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test236 is test do
+               var md = """1.     indented code\n\n   paragraph\n\n       more code\n"""
+               var html = """<ol>\n<li>\n<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test237 is test do
+               var md = """1.      indented code\n\n   paragraph\n\n       more code\n"""
+               var html = """<ol>\n<li>\n<pre><code> indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test238 is test do
+               var md = """   foo\n\nbar\n"""
+               var html = """<p>foo</p>\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test239 is test do
+               var md = """-    foo\n\n  bar\n"""
+               var html = """<ul>\n<li>foo</li>\n</ul>\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test240 is test do
+               var md = """-  foo\n\n   bar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test241 is test do
+               var md = """-\n  foo\n-\n  ```\n  bar\n  ```\n-\n      baz\n"""
+               var html = """<ul>\n<li>foo</li>\n<li>\n<pre><code>bar\n</code></pre>\n</li>\n<li>\n<pre><code>baz\n</code></pre>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test242 is test do
+               var md = """-   \n  foo\n"""
+               var html = """<ul>\n<li>foo</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test243 is test do
+               var md = """-\n\n  foo\n"""
+               var html = """<ul>\n<li></li>\n</ul>\n<p>foo</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test244 is test do
+               var md = """- foo\n-\n- bar\n"""
+               var html = """<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test245 is test do
+               var md = """- foo\n-   \n- bar\n"""
+               var html = """<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test246 is test do
+               var md = """1. foo\n2.\n3. bar\n"""
+               var html = """<ol>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test247 is test do
+               var md = """*\n"""
+               var html = """<ul>\n<li></li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test248 is test do
+               var md = """foo\n*\n\nfoo\n1.\n"""
+               var html = """<p>foo\n*</p>\n<p>foo\n1.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test249 is test do
+               var md = """ 1.  A paragraph\n     with two lines.\n\n         indented code\n\n     > A block quote.\n"""
+               var html = """<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test250 is test do
+               var md = """  1.  A paragraph\n      with two lines.\n\n          indented code\n\n      > A block quote.\n"""
+               var html = """<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test251 is test do
+               var md = """   1.  A paragraph\n       with two lines.\n\n           indented code\n\n       > A block quote.\n"""
+               var html = """<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test252 is test do
+               var md = """    1.  A paragraph\n        with two lines.\n\n            indented code\n\n        > A block quote.\n"""
+               var html = """<pre><code>1.  A paragraph\n    with two lines.\n\n        indented code\n\n    &gt; A block quote.\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test253 is test do
+               var md = """  1.  A paragraph\nwith two lines.\n\n          indented code\n\n      > A block quote.\n"""
+               var html = """<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test254 is test do
+               var md = """  1.  A paragraph\n    with two lines.\n"""
+               var html = """<ol>\n<li>A paragraph\nwith two lines.</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test255 is test do
+               var md = """> 1. > Blockquote\ncontinued here.\n"""
+               var html = """<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test256 is test do
+               var md = """> 1. > Blockquote\n> continued here.\n"""
+               var html = """<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test257 is test do
+               var md = """- foo\n  - bar\n    - baz\n      - boo\n"""
+               var html = """<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test258 is test do
+               var md = """- foo\n - bar\n  - baz\n   - boo\n"""
+               var html = """<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test259 is test do
+               var md = """10) foo\n    - bar\n"""
+               var html = """<ol start="10">\n<li>foo\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test260 is test do
+               var md = """10) foo\n   - bar\n"""
+               var html = """<ol start="10">\n<li>foo</li>\n</ol>\n<ul>\n<li>bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test261 is test do
+               var md = """- - foo\n"""
+               var html = """<ul>\n<li>\n<ul>\n<li>foo</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test262 is test do
+               var md = """1. - 2. foo\n"""
+               var html = """<ol>\n<li>\n<ul>\n<li>\n<ol start="2">\n<li>foo</li>\n</ol>\n</li>\n</ul>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test263 is test do
+               var md = """- # Foo\n- Bar\n  ---\n  baz\n"""
+               var html = """<ul>\n<li>\n<h1>Foo</h1>\n</li>\n<li>\n<h2>Bar</h2>\nbaz</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_lists.nit b/lib/markdown2/tests/test_commonmark_lists.nit
new file mode 100644 (file)
index 0000000..05ef4d4
--- /dev/null
@@ -0,0 +1,166 @@
+# 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.
+
+module test_commonmark_lists is test
+
+import test_markdown
+
+class TestCommonmarkLists
+       super TestMarkdownHtml
+       test
+
+       fun test264 is test do
+               var md = """- foo\n- bar\n+ baz\n"""
+               var html = """<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<ul>\n<li>baz</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test265 is test do
+               var md = """1. foo\n2. bar\n3) baz\n"""
+               var html = """<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>\n<ol start="3">\n<li>baz</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test266 is test do
+               var md = """Foo\n- bar\n- baz\n"""
+               var html = """<p>Foo</p>\n<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test267 is test do
+               var md = """The number of windows in my house is\n14.  The number of doors is 6.\n"""
+               var html = """<p>The number of windows in my house is\n14.  The number of doors is 6.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test268 is test do
+               var md = """The number of windows in my house is\n1.  The number of doors is 6.\n"""
+               var html = """<p>The number of windows in my house is</p>\n<ol>\n<li>The number of doors is 6.</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test269 is test do
+               var md = """- foo\n\n- bar\n\n\n- baz\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n</li>\n<li>\n<p>bar</p>\n</li>\n<li>\n<p>baz</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test270 is test do
+               var md = """- foo\n  - bar\n    - baz\n\n\n      bim\n"""
+               var html = """<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>\n<p>baz</p>\n<p>bim</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test271 is test do
+               var md = """- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim\n"""
+               var html = """<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test272 is test do
+               var md = """-   foo\n\n    notcode\n\n-   foo\n\n<!-- -->\n\n    code\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test273 is test do
+               var md = """- a\n - b\n  - c\n   - d\n  - e\n - f\n- g\n"""
+               var html = """<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n<li>e</li>\n<li>f</li>\n<li>g</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test274 is test do
+               var md = """1. a\n\n  2. b\n\n   3. c\n"""
+               var html = """<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test277 is test do
+               var md = """- a\n- b\n\n- c\n"""
+               var html = """<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test278 is test do
+               var md = """* a\n*\n\n* c\n"""
+               var html = """<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test279 is test do
+               var md = """- a\n- b\n\n  c\n- d\n"""
+               var html = """<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test280 is test do
+               var md = """- a\n- b\n\n  [ref]: /url\n- d\n"""
+               var html = """<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test281 is test do
+               var md = """- a\n- ```\n  b\n\n\n  ```\n- c\n"""
+               var html = """<ul>\n<li>a</li>\n<li>\n<pre><code>b\n\n\n</code></pre>\n</li>\n<li>c</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test282 is test do
+               var md = """- a\n  - b\n\n    c\n- d\n"""
+               var html = """<ul>\n<li>a\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n<li>d</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test283 is test do
+               var md = """* a\n  > b\n  >\n* c\n"""
+               var html = """<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n</li>\n<li>c</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test284 is test do
+               var md = """- a\n  > b\n  ```\n  c\n  ```\n- d\n"""
+               var html = """<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n<pre><code>c\n</code></pre>\n</li>\n<li>d</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test285 is test do
+               var md = """- a\n"""
+               var html = """<ul>\n<li>a</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test286 is test do
+               var md = """- a\n  - b\n"""
+               var html = """<ul>\n<li>a\n<ul>\n<li>b</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test287 is test do
+               var md = """1. ```\n   foo\n   ```\n\n   bar\n"""
+               var html = """<ol>\n<li>\n<pre><code>foo\n</code></pre>\n<p>bar</p>\n</li>\n</ol>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test288 is test do
+               var md = """* foo\n  * bar\n\n  baz\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>baz</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test289 is test do
+               var md = """- a\n  - b\n  - c\n\n- d\n  - e\n  - f\n"""
+               var html = """<ul>\n<li>\n<p>a</p>\n<ul>\n<li>b</li>\n<li>c</li>\n</ul>\n</li>\n<li>\n<p>d</p>\n<ul>\n<li>e</li>\n<li>f</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_paragraphs.nit b/lib/markdown2/tests/test_commonmark_paragraphs.nit
new file mode 100644 (file)
index 0000000..6501c95
--- /dev/null
@@ -0,0 +1,70 @@
+# 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.
+
+module test_commonmark_paragraphs is test
+
+import test_markdown
+
+class TestCommonmarkParagraphs
+       super TestMarkdownHtml
+       test
+
+       fun test182 is test do
+               var md = """aaa\n\nbbb\n"""
+               var html = """<p>aaa</p>\n<p>bbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test183 is test do
+               var md = """aaa\nbbb\n\nccc\nddd\n"""
+               var html = """<p>aaa\nbbb</p>\n<p>ccc\nddd</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test184 is test do
+               var md = """aaa\n\n\nbbb\n"""
+               var html = """<p>aaa</p>\n<p>bbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test185 is test do
+               var md = """  aaa\n bbb\n"""
+               var html = """<p>aaa\nbbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test186 is test do
+               var md = """aaa\n             bbb\n                                       ccc\n"""
+               var html = """<p>aaa\nbbb\nccc</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test187 is test do
+               var md = """   aaa\nbbb\n"""
+               var html = """<p>aaa\nbbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test188 is test do
+               var md = """    aaa\nbbb\n"""
+               var html = """<pre><code>aaa\n</code></pre>\n<p>bbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test189 is test do
+               var md = """aaa     \nbbb     \n"""
+               var html = """<p>aaa<br />\nbbb</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_precedence.nit b/lib/markdown2/tests/test_commonmark_precedence.nit
new file mode 100644 (file)
index 0000000..a9938c0
--- /dev/null
@@ -0,0 +1,28 @@
+# 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.
+
+module test_commonmark_precedence is test
+
+import test_markdown
+
+class TestCommonmarkPrecedence
+       super TestMarkdownHtml
+       test
+
+       fun test12 is test do
+               var md = """- `one\n- two`\n"""
+               var html = """<ul>\n<li>`one</li>\n<li>two`</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_raw_html.nit b/lib/markdown2/tests/test_commonmark_raw_html.nit
new file mode 100644 (file)
index 0000000..9e05a46
--- /dev/null
@@ -0,0 +1,148 @@
+# 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.
+
+module test_commonmark_raw_html is test
+
+import test_markdown
+
+class TestCommonmarkRawHTML
+       super TestMarkdownHtml
+       test
+
+       fun test587 is test do
+               var md = """<a><bab><c2c>\n"""
+               var html = """<p><a><bab><c2c></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test588 is test do
+               var md = """<a/><b2/>\n"""
+               var html = """<p><a/><b2/></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test589 is test do
+               var md = """<a  /><b2\ndata="foo" >\n"""
+               var html = """<p><a  /><b2\ndata="foo" ></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test590 is test do
+               var md = """<a foo="bar" bam = 'baz <em>"</em>'\n_boolean zoop:33=zoop:33 />\n"""
+               var html = """<p><a foo="bar" bam = 'baz <em>"</em>'\n_boolean zoop:33=zoop:33 /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test591 is test do
+               var md = """Foo <responsive-image src="foo.jpg" />\n"""
+               var html = """<p>Foo <responsive-image src="foo.jpg" /></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test592 is test do
+               var md = """<33> <__>\n"""
+               var html = """<p>&lt;33&gt; &lt;__&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test593 is test do
+               var md = """<a h*#ref="hi">\n"""
+               var html = """<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test594 is test do
+               var md = """<a href="hi'> <a href=hi'>\n"""
+               var html = """<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test595 is test do
+               var md = """< a><\nfoo><bar/ >\n<foo bar=baz\nbim!bop />\n"""
+               var html = """<p>&lt; a&gt;&lt;\nfoo&gt;&lt;bar/ &gt;\n&lt;foo bar=baz\nbim!bop /&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test596 is test do
+               var md = """<a href='bar'title=title>\n"""
+               var html = """<p>&lt;a href='bar'title=title&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test597 is test do
+               var md = """</a></foo >\n"""
+               var html = """<p></a></foo ></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test598 is test do
+               var md = """</a href="foo">\n"""
+               var html = """<p>&lt;/a href=&quot;foo&quot;&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test599 is test do
+               var md = """foo <!-- this is a\ncomment - with hyphen -->\n"""
+               var html = """<p>foo <!-- this is a\ncomment - with hyphen --></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test600 is test do
+               var md = """foo <!-- not a comment -- two hyphens -->\n"""
+               var html = """<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test601 is test do
+               var md = """foo <!--> foo -->\n\nfoo <!-- foo--->\n"""
+               var html = """<p>foo &lt;!--&gt; foo --&gt;</p>\n<p>foo &lt;!-- foo---&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test602 is test do
+               var md = """foo <?php echo $a; ?>\n"""
+               var html = """<p>foo <?php echo $a; ?></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test603 is test do
+               var md = """foo <!ELEMENT br EMPTY>\n"""
+               var html = """<p>foo <!ELEMENT br EMPTY></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test604 is test do
+               var md = """foo <![CDATA[>&<]]>\n"""
+               var html = """<p>foo <![CDATA[>&<]]></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test605 is test do
+               var md = """foo <a href="&ouml;">\n"""
+               var html = """<p>foo <a href="&ouml;"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test606 is test do
+               var md = """foo <a href="\\*">\n"""
+               var html = """<p>foo <a href="\\*"></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test607 is test do
+               var md = """<a href="\\"">\n"""
+               var html = """<p>&lt;a href=&quot;&quot;&quot;&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_setext_headings.nit b/lib/markdown2/tests/test_commonmark_setext_headings.nit
new file mode 100644 (file)
index 0000000..c92f4d0
--- /dev/null
@@ -0,0 +1,178 @@
+# 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.
+
+module test_commonmark_setext_headings is test
+
+import test_markdown
+
+class TestCommonmarkSetextHeadings
+       super TestMarkdownHtml
+       test
+
+       fun test50 is test do
+               var md = """Foo *bar*\n=========\n\nFoo *bar*\n---------\n"""
+               var html = """<h1>Foo <em>bar</em></h1>\n<h2>Foo <em>bar</em></h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test51 is test do
+               var md = """Foo *bar\nbaz*\n====\n"""
+               var html = """<h1>Foo <em>bar\nbaz</em></h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test52 is test do
+               var md = """Foo\n-------------------------\n\nFoo\n=\n"""
+               var html = """<h2>Foo</h2>\n<h1>Foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test53 is test do
+               var md = """   Foo\n---\n\n  Foo\n-----\n\n  Foo\n  ===\n"""
+               var html = """<h2>Foo</h2>\n<h2>Foo</h2>\n<h1>Foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test54 is test do
+               var md = """    Foo\n    ---\n\n    Foo\n---\n"""
+               var html = """<pre><code>Foo\n---\n\nFoo\n</code></pre>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test55 is test do
+               var md = """Foo\n   ----      \n"""
+               var html = """<h2>Foo</h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test56 is test do
+               var md = """Foo\n    ---\n"""
+               var html = """<p>Foo\n---</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test57 is test do
+               var md = """Foo\n= =\n\nFoo\n--- -\n"""
+               var html = """<p>Foo\n= =</p>\n<p>Foo</p>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test58 is test do
+               var md = """Foo  \n-----\n"""
+               var html = """<h2>Foo</h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test59 is test do
+               var md = """Foo\\\n----\n"""
+               var html = """<h2>Foo\\</h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test60 is test do
+               var md = """`Foo\n----\n`\n\n<a title="a lot\n---\nof dashes"/>\n"""
+               var html = """<h2>`Foo</h2>\n<p>`</p>\n<h2>&lt;a title=&quot;a lot</h2>\n<p>of dashes&quot;/&gt;</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test61 is test do
+               var md = """> Foo\n---\n"""
+               var html = """<blockquote>\n<p>Foo</p>\n</blockquote>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test62 is test do
+               var md = """> foo\nbar\n===\n"""
+               var html = """<blockquote>\n<p>foo\nbar\n===</p>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test63 is test do
+               var md = """- Foo\n---\n"""
+               var html = """<ul>\n<li>Foo</li>\n</ul>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test64 is test do
+               var md = """Foo\nBar\n---\n"""
+               var html = """<h2>Foo\nBar</h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test65 is test do
+               var md = """---\nFoo\n---\nBar\n---\nBaz\n"""
+               var html = """<hr />\n<h2>Foo</h2>\n<h2>Bar</h2>\n<p>Baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test66 is test do
+               var md = """\n====\n"""
+               var html = """<p>====</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test67 is test do
+               var md = """---\n---\n"""
+               var html = """<hr />\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test68 is test do
+               var md = """- foo\n-----\n"""
+               var html = """<ul>\n<li>foo</li>\n</ul>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test69 is test do
+               var md = """    foo\n---\n"""
+               var html = """<pre><code>foo\n</code></pre>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test70 is test do
+               var md = """> foo\n-----\n"""
+               var html = """<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test71 is test do
+               var md = """\\> foo\n------\n"""
+               var html = """<h2>&gt; foo</h2>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test72 is test do
+               var md = """Foo\n\nbar\n---\nbaz\n"""
+               var html = """<p>Foo</p>\n<h2>bar</h2>\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test73 is test do
+               var md = """Foo\nbar\n\n---\n\nbaz\n"""
+               var html = """<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test74 is test do
+               var md = """Foo\nbar\n* * *\nbaz\n"""
+               var html = """<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test75 is test do
+               var md = """Foo\nbar\n\\---\nbaz\n"""
+               var html = """<p>Foo\nbar\n---\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_soft_line_breaks.nit b/lib/markdown2/tests/test_commonmark_soft_line_breaks.nit
new file mode 100644 (file)
index 0000000..c3ce0f1
--- /dev/null
@@ -0,0 +1,34 @@
+# 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.
+
+module test_commonmark_soft_line_breaks is test
+
+import test_markdown
+
+class TestCommonmarkSoftLineBreaks
+       super TestMarkdownHtml
+       test
+
+       fun test623 is test do
+               var md = """foo\nbaz\n"""
+               var html = """<p>foo\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test624 is test do
+               var md = """foo \n baz\n"""
+               var html = """<p>foo\nbaz</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_tabs.nit b/lib/markdown2/tests/test_commonmark_tabs.nit
new file mode 100644 (file)
index 0000000..2a2f2ca
--- /dev/null
@@ -0,0 +1,88 @@
+# 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.
+
+module test_commonmark_tabs is test
+
+import test_markdown
+
+class TestCommonmarkTabs
+       super TestMarkdownHtml
+       test
+
+       fun test1 is test do
+               var md = """\tfoo\tbaz\t\tbim\n"""
+               var html = """<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test2 is test do
+               var md = """  \tfoo\tbaz\t\tbim\n"""
+               var html = """<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test3 is test do
+               var md = """    a\ta\n    ὐ\ta\n"""
+               var html = """<pre><code>a\ta\nὐ\ta\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test4 is test do
+               var md = """  - foo\n\n\tbar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test5 is test do
+               var md = """- foo\n\n\t\tbar\n"""
+               var html = """<ul>\n<li>\n<p>foo</p>\n<pre><code>  bar\n</code></pre>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test6 is test do
+               var md = """>\t\tfoo\n"""
+               var html = """<blockquote>\n<pre><code>  foo\n</code></pre>\n</blockquote>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test7 is test do
+               var md = """-\t\tfoo\n"""
+               var html = """<ul>\n<li>\n<pre><code>  foo\n</code></pre>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test8 is test do
+               var md = """    foo\n\tbar\n"""
+               var html = """<pre><code>foo\nbar\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test9 is test do
+               var md = """ - foo\n   - bar\n\t - baz\n"""
+               var html = """<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test10 is test do
+               var md = """#\tFoo\n"""
+               var html = """<h1>Foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test11 is test do
+               var md = """*\t*\t*\t\n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_textual_content.nit b/lib/markdown2/tests/test_commonmark_textual_content.nit
new file mode 100644 (file)
index 0000000..235e20e
--- /dev/null
@@ -0,0 +1,40 @@
+# 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.
+
+module test_commonmark_textual_content is test
+
+import test_markdown
+
+class TestCommonmarkTextualContent
+       super TestMarkdownHtml
+       test
+
+       fun test625 is test do
+               var md = """hello $.;'there\n"""
+               var html = """<p>hello $.;'there</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test626 is test do
+               var md = """Foo χρῆν\n"""
+               var html = """<p>Foo χρῆν</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test627 is test do
+               var md = """Multiple     spaces\n"""
+               var html = """<p>Multiple     spaces</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_commonmark_thematic_breaks.nit b/lib/markdown2/tests/test_commonmark_thematic_breaks.nit
new file mode 100644 (file)
index 0000000..ae68fa4
--- /dev/null
@@ -0,0 +1,136 @@
+# 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.
+
+module test_commonmark_thematic_breaks is test
+
+import test_markdown
+
+class TestCommonmarkThematicBreaks
+       super TestMarkdownHtml
+       test
+
+       fun test13 is test do
+               var md = """***\n---\n___\n"""
+               var html = """<hr />\n<hr />\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test14 is test do
+               var md = """+++\n"""
+               var html = """<p>+++</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test15 is test do
+               var md = """===\n"""
+               var html = """<p>===</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test16 is test do
+               var md = """--\n**\n__\n"""
+               var html = """<p>--\n**\n__</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test17 is test do
+               var md = """ ***\n  ***\n   ***\n"""
+               var html = """<hr />\n<hr />\n<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test18 is test do
+               var md = """    ***\n"""
+               var html = """<pre><code>***\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test19 is test do
+               var md = """Foo\n    ***\n"""
+               var html = """<p>Foo\n***</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test20 is test do
+               var md = """_____________________________________\n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test21 is test do
+               var md = """ - - -\n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test22 is test do
+               var md = """ **  * ** * ** * **\n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test23 is test do
+               var md = """-     -      -      -\n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test24 is test do
+               var md = """- - - -    \n"""
+               var html = """<hr />\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test25 is test do
+               var md = """_ _ _ _ a\n\na------\n\n---a---\n"""
+               var html = """<p>_ _ _ _ a</p>\n<p>a------</p>\n<p>---a---</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test26 is test do
+               var md = """ *-*\n"""
+               var html = """<p><em>-</em></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test27 is test do
+               var md = """- foo\n***\n- bar\n"""
+               var html = """<ul>\n<li>foo</li>\n</ul>\n<hr />\n<ul>\n<li>bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test28 is test do
+               var md = """Foo\n***\nbar\n"""
+               var html = """<p>Foo</p>\n<hr />\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test29 is test do
+               var md = """Foo\n---\nbar\n"""
+               var html = """<h2>Foo</h2>\n<p>bar</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test30 is test do
+               var md = """* Foo\n* * *\n* Bar\n"""
+               var html = """<ul>\n<li>Foo</li>\n</ul>\n<hr />\n<ul>\n<li>Bar</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test31 is test do
+               var md = """- Foo\n- * * *\n"""
+               var html = """<ul>\n<li>Foo</li>\n<li>\n<hr />\n</li>\n</ul>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown.nit b/lib/markdown2/tests/test_markdown.nit
new file mode 100644 (file)
index 0000000..60f1f34
--- /dev/null
@@ -0,0 +1,42 @@
+# 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.
+
+# Test suites for module `markdown`
+module test_markdown
+
+import markdown_html_rendering
+
+# Abstract test class that instanciates the markdown parser
+abstract class TestMarkdown
+
+       # Markdown parser to use in tests
+       var md_parser = new MdParser
+
+       # Parse a `md` string as a MdNode
+       fun parse_md(md: String): MdNode do return md_parser.parse(md)
+end
+
+# Abstract test class that defines the test methods for HTML rendering
+abstract class TestMarkdownHtml
+       super TestMarkdown
+
+       # HTML renderer used in tests
+       var html_renderer = new HtmlRenderer
+
+       # Render the `md` string as HTML
+       fun md_to_html(md: String): String do
+               var node = parse_md(md)
+               return html_renderer.render(node)
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_blocks.nit b/lib/markdown2/tests/test_markdown_blocks.nit
new file mode 100644 (file)
index 0000000..f81d225
--- /dev/null
@@ -0,0 +1,660 @@
+# 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 htmlress or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Test for markdown blocks parsing
+module test_markdown_blocks is test
+
+import test_markdown
+
+class TestMarkdownBlocks
+       super TestMarkdownHtml
+       test
+
+       fun test_blocks_empty is test do
+               var md = ""
+               var html = ""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_tabs is test do
+               var md = """\tsome code\n"""
+               var html = """<pre><code>some code\n</code></pre>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_pagraph1 is test do
+               var md = "test\n"
+               var html = "<p>test</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_pagraph2 is test do
+               var md = """line1\nline2\n\nline3 line4\n\nline5\n"""
+               var html = """<p>line1\nline2</p>\n<p>line3 line4</p>\n<p>line5</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_pagraph3 is test do
+               var md = """
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+
+Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
+<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_headings_1 is test do
+               var md = """
+This is a H1
+=============
+
+This is a H2
+-------------
+"""
+               var html = """
+<h1>This is a H1</h1>
+<h2>This is a H2</h2>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_headings_2 is test do
+               var md = """
+# This is a H1
+
+## This is a H2
+###### This is a H6
+"""
+               var html = """
+<h1>This is a H1</h1>
+<h2>This is a H2</h2>
+<h6>This is a H6</h6>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_headings_3 is test do
+               var md = """
+# This is a H1 #
+
+## This is a H2 ##
+
+### This is a H3 ######
+"""
+               var html = """
+<h1>This is a H1</h1>
+<h2>This is a H2</h2>
+<h3>This is a H3</h3>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_hr1 is test do
+               var md = """
+* * *
+
+***
+
+*****
+
+- - -
+
+---------------------------------------
+"""
+               var html = "<hr />\n<hr />\n<hr />\n<hr />\n<hr />\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_bquote1 is test do
+               var md = """
+> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+>
+> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+> id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """<blockquote>
+<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
+<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.</p>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_bquote2 is test do
+               var md = """
+> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+
+> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """<blockquote>
+<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
+</blockquote>
+<blockquote>
+<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.</p>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_bquote3 is test do
+               var md = """
+> This is the first level of quoting.
+>
+> > This is nested blockquote.
+>
+> Back to the first level.
+"""
+               var html = """<blockquote>
+<p>This is the first level of quoting.</p>
+<blockquote>
+<p>This is nested blockquote.</p>
+</blockquote>
+<p>Back to the first level.</p>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list1 is test do
+               var md = """
+*   Red
+*   Green
+*   Blue
+"""
+               var html = """<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list2 is test do
+               var md = """
++   Red
++   Green
++   Blue
+"""
+               var html = """<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list3 is test do
+               var md = """
+-   Red
+-   Green
+-   Blue
+"""
+               var html = """<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list4 is test do
+               var md = """
+1.  Bird
+2.  McHale
+3.  Parish
+"""
+               var html = """<ol>
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list5 is test do
+               var md = """
+3. Bird
+1. McHale
+8. Parish
+"""
+               var html = """<ol start=\"3\">
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list6 is test do
+               var md = """
+*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+    viverra nec, fringilla in, laoreet vitae, risus.
+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+    Suspendisse id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """
+<ul>
+<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.</li>
+<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list7 is test do
+               var md = """
+*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.
+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """
+<ul>
+<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.</li>
+<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list8 is test do
+               var md = """
+*   Bird
+
+*   Magic
+"""
+               var html = """
+<ul>
+<li>
+<p>Bird</p>
+</li>
+<li>
+<p>Magic</p>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list9 is test do
+               var md = """
+1.  This is a list item with two paragraphs. Lorem ipsum dolor
+    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
+    mi posuere lectus.
+
+    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
+    sit amet velit.
+
+2.  Suspendisse id sem consectetuer libero luctus adipiscing.
+"""
+               var html = """
+<ol>
+<li>
+<p>This is a list item with two paragraphs. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit. Aliquam hendrerit
+mi posuere lectus.</p>
+<p>Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
+sit amet velit.</p>
+</li>
+<li>
+<p>Suspendisse id sem consectetuer libero luctus adipiscing.</p>
+</li>
+</ol>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list10 is test do
+               var md = """
+*   This is a list item with two paragraphs.
+
+    This is the second paragraph in the list item. You're
+only required to indent the first line. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit.
+
+*   Another item in the same list.
+"""
+               var html = """
+<ul>
+<li>
+<p>This is a list item with two paragraphs.</p>
+<p>This is the second paragraph in the list item. You're
+only required to indent the first line. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit.</p>
+</li>
+<li>
+<p>Another item in the same list.</p>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_list_ext is test do
+               var md = """
+This is a paragraph
+* and this is a list
+"""
+               var html = """
+<p>This is a paragraph</p>
+<ul>
+<li>and this is a list</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_indented_code1 is test do
+               var md = """
+This is a normal paragraph:
+
+    This is a code block.
+"""
+               var html = """<p>This is a normal paragraph:</p>
+<pre><code>This is a code block.
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_indented_code2 is test do
+               var md = """
+Here is an example of AppleScript:
+
+    tell application "Foo"
+        beep
+    end tell
+
+    <div class="footer">
+        &copy; 2004 Foo Corporation
+    </div>
+"""
+               var html = """
+<p>Here is an example of AppleScript:</p>
+<pre><code>tell application &quot;Foo&quot;
+    beep
+end tell
+
+&lt;div class=&quot;footer&quot;&gt;
+    &amp;copy; 2004 Foo Corporation
+&lt;/div&gt;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_indented_code3 is test do
+               var md = """
+Here is an example of AppleScript:
+
+    beep
+"""
+               var html = """
+<p>Here is an example of AppleScript:</p>
+<pre><code>beep
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_fenced_code1 is test do
+               var md = """
+Here is an example of AppleScript:
+~~~
+tell application "Foo"
+    beep
+end tell
+
+<div class="footer">
+    &copy; 2004 Foo Corporation
+</div>
+~~~
+"""
+               var html = """
+<p>Here is an example of AppleScript:</p>
+<pre><code>tell application &quot;Foo&quot;
+    beep
+end tell
+
+&lt;div class=&quot;footer&quot;&gt;
+    &amp;copy; 2004 Foo Corporation
+&lt;/div&gt;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_fenced_code2 is test do
+               var md = """
+Here is an example of AppleScript:
+```
+tell application "Foo"
+    beep
+end tell
+
+<div class="footer">
+    &copy; 2004 Foo Corporation
+</div>
+```
+"""
+               var html = """
+<p>Here is an example of AppleScript:</p>
+<pre><code>tell application &quot;Foo&quot;
+    beep
+end tell
+
+&lt;div class=&quot;footer&quot;&gt;
+    &amp;copy; 2004 Foo Corporation
+&lt;/div&gt;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_fenced_code3 is test do
+               var md = """
+```nit
+print "Hello World!"
+```
+"""
+               var html = """
+<pre><code class="language-nit">print &quot;Hello World!&quot;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_fenced_code4 is test do
+               var md = """
+~~~
+print "Hello"
+~~~
+~~~
+print "World"
+~~~
+"""
+               var html = """
+<pre><code>print &quot;Hello&quot;
+</code></pre>
+<pre><code>print &quot;World&quot;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_fenced_code5 is test do
+               var md = """
+~~~
+print "Hello"
+~~~
+~~~
+print "World"
+~~~
+"""
+               var html = """
+<pre><code>print &quot;Hello&quot;
+</code></pre>
+<pre><code>print &quot;World&quot;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_nesting1 is test do
+               var md = """
+> ## This is a header.
+>
+> 1.   This is the first list item.
+> 2.   This is the second list item.
+>
+> Here's some example code:
+>
+>     return shell_exec("echo $input | $markdown_script");
+"""
+               var html = """
+<blockquote>
+<h2>This is a header.</h2>
+<ol>
+<li>This is the first list item.</li>
+<li>This is the second list item.</li>
+</ol>
+<p>Here's some example code:</p>
+<pre><code>return shell_exec(&quot;echo $input | $markdown_script&quot;);
+</code></pre>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_nesting2 is test do
+               var md = """
+*   A list item with a blockquote:
+
+    > This is a blockquote
+    > inside a list item.
+"""
+               var html = """
+<ul>
+<li>
+<p>A list item with a blockquote:</p>
+<blockquote>
+<p>This is a blockquote
+inside a list item.</p>
+</blockquote>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_nesting3 is test do
+               var md = """
+*   A list item with a code block:
+
+        <code goes here>
+"""
+               var html = """
+<ul>
+<li>
+<p>A list item with a code block:</p>
+<pre><code>&lt;code goes here&gt;
+</code></pre>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_nesting4 is test do
+               var md = """
+*      Tab
+       *       Tab
+               *       Tab
+"""
+               var html = """
+<ul>
+<li>Tab
+<ul>
+<li>Tab
+<ul>
+<li>Tab</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_blocks_nesting5 is test do
+                       var md = """
+*      this
+
+       *       sub
+
+               that
+"""
+                       var html = """
+<ul>
+<li>
+<p>this</p>
+<ul>
+<li>
+<p>sub</p>
+<p>that</p>
+</li>
+</ul>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_daring.nit b/lib/markdown2/tests/test_markdown_daring.nit
new file mode 100644 (file)
index 0000000..962e356
--- /dev/null
@@ -0,0 +1,1343 @@
+# 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 htmlress or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Markdown tests from DaringFireball
+#
+# See <https://daringfireball.net/projects/markdown/>.
+module test_markdown_daring is test
+
+import test_markdown
+
+class TestMarkdownDaring
+       super TestMarkdownHtml
+       test
+
+       fun test_daring_encoding is test do
+               var md = """
+AT&T has an ampersand in their name.
+
+AT&amp;T is another way to write it.
+
+This & that.
+
+4 < 5.
+
+6 > 5.
+
+Here's a [link][1] with an ampersand in the URL.
+
+Here's a link with an ampersand in the link text: [AT&T][2].
+
+Here's an inline [link](/script?foo=1&bar=2).
+
+Here's an inline [link](</script?foo=1&bar=2>).
+
+
+[1]: http://example.com/?foo=1&bar=2
+[2]: http://att.com/  "AT&T"
+"""
+
+               var html = """
+<p>AT&amp;T has an ampersand in their name.</p>
+<p>AT&amp;T is another way to write it.</p>
+<p>This &amp; that.</p>
+<p>4 &lt; 5.</p>
+<p>6 &gt; 5.</p>
+<p>Here's a <a href="http://example.com/?foo=1&amp;bar=2">link</a> with an ampersand in the URL.</p>
+<p>Here's a link with an ampersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>
+<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
+<p>Here's an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_autolinks is test do
+               var md = """
+Link: <http://example.com/>.
+
+With an ampersand: <http://example.com/?foo=1&bar=2>
+
+* In a list?
+* <http://example.com/>
+* It should.
+
+> Blockquoted: <http://example.com/>
+
+Auto-links should not occur here: `<http://example.com/>`
+
+       or here: <http://example.com/>
+"""
+
+               var html = """
+<p>Link: <a href="http://example.com/">http://example.com/</a>.</p>
+<p>With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>
+<ul>
+<li>In a list?</li>
+<li><a href="http://example.com/">http://example.com/</a></li>
+<li>It should.</li>
+</ul>
+<blockquote>
+<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>
+</blockquote>
+<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
+<pre><code>or here: &lt;http://example.com/&gt;
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_escape is test do
+               var md = """
+These should all get escaped:
+
+Backslash: \\
+
+Backtick: \`
+
+Asterisk: \*
+
+Underscore: \_
+
+Left brace: \{
+
+Right brace: \}
+
+Left bracket: \[
+
+Right bracket: \]
+
+Left paren: \(
+
+Right paren: \)
+
+Greater-than: \>
+
+Hash: \#
+
+Period: \.
+
+Bang: \!
+
+Plus: \+
+
+Minus: \-
+
+
+These should not, because they occur within a code block:
+
+       Backslash: \\
+
+       Backtick: \`
+
+       Asterisk: \*
+
+       Underscore: \_
+
+       Left brace: \{
+
+       Right brace: \}
+
+       Left bracket: \[
+
+       Right bracket: \]
+
+       Left paren: \(
+
+       Right paren: \)
+
+       Greater-than: \>
+
+       Hash: \#
+
+       Period: \.
+
+       Bang: \!
+
+       Plus: \+
+
+       Minus: \-
+
+Nor should these, which occur in code spans:
+
+Backslash: `\\`
+
+Backtick: `` \` ``
+
+Asterisk: `\*`
+
+Underscore: `\_`
+
+Left brace: `\{`
+
+Right brace: `\}`
+
+Left bracket: `\[`
+
+Right bracket: `\]`
+
+Left paren: `\(`
+
+Right paren: `\)`
+
+Greater-than: `\>`
+
+Hash: `\#`
+
+Period: `\.`
+
+Bang: `\!`
+
+Plus: `\+`
+
+Minus: `\-`
+
+These should get escaped, even though they're matching pairs for
+other Markdown constructs:
+
+\\\*asterisks\\\*
+
+\\\_underscores\\\_
+
+\\\`backticks\\\`
+
+This is a code span with a literal backslash-backtick sequence: `` \` ``
+
+This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.
+
+This is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.
+"""
+               var html = """
+<p>These should all get escaped:</p>
+<p>Backslash: \\</p>
+<p>Backtick: \`</p>
+<p>Asterisk: \*</p>
+<p>Underscore: \_</p>
+<p>Left brace: \{</p>
+<p>Right brace: \}</p>
+<p>Left bracket: \[</p>
+<p>Right bracket: \]</p>
+<p>Left paren: \(</p>
+<p>Right paren: \)</p>
+<p>Greater-than: &gt;</p>
+<p>Hash: \#</p>
+<p>Period: \.</p>
+<p>Bang: \!</p>
+<p>Plus: \+</p>
+<p>Minus: \-</p>
+<p>These should not, because they occur within a code block:</p>
+<pre><code>Backslash: \\
+
+Backtick: \`
+
+Asterisk: \*
+
+Underscore: \_
+
+Left brace: \{
+
+Right brace: \}
+
+Left bracket: \[
+
+Right bracket: \]
+
+Left paren: \(
+
+Right paren: \)
+
+Greater-than: \&gt;
+
+Hash: \#
+
+Period: \.
+
+Bang: \!
+
+Plus: \+
+
+Minus: \-
+</code></pre>
+<p>Nor should these, which occur in code spans:</p>
+<p>Backslash: <code>\\</code></p>
+<p>Backtick: <code>\`</code></p>
+<p>Asterisk: <code>\*</code></p>
+<p>Underscore: <code>\_</code></p>
+<p>Left brace: <code>\{</code></p>
+<p>Right brace: <code>\}</code></p>
+<p>Left bracket: <code>\[</code></p>
+<p>Right bracket: <code>\]</code></p>
+<p>Left paren: <code>\(</code></p>
+<p>Right paren: <code>\)</code></p>
+<p>Greater-than: <code>\&gt;</code></p>
+<p>Hash: <code>\#</code></p>
+<p>Period: <code>\.</code></p>
+<p>Bang: <code>\!</code></p>
+<p>Plus: <code>\+</code></p>
+<p>Minus: <code>\-</code></p>
+<p>These should get escaped, even though they're matching pairs for
+other Markdown constructs:</p>
+<p>*asterisks*</p>
+<p>_underscores_</p>
+<p>`backticks`</p>
+<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p>
+<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>
+<p>This is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.</p>
+"""
+
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_blockquotes is test do
+               var md = """
+> Example:
+>
+>     sub status {
+>         print "working";
+>     }
+>
+> Or:
+>
+>     sub status {
+>         return "working";
+>     }
+"""
+
+               var html = """
+<blockquote>
+<p>Example:</p>
+<pre><code>sub status {
+    print &quot;working&quot;;
+}
+</code></pre>
+<p>Or:</p>
+<pre><code>sub status {
+    return &quot;working&quot;;
+}
+</code></pre>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_code_blocks is test do
+               var md = """
+       code block on the first line
+
+Regular text.
+
+    code block indented by spaces
+
+Regular text.
+
+       the lines in this block
+       all contain trailing spaces
+
+Regular Text.
+
+       code block on the last line
+"""
+
+               var html = """
+<pre><code>code block on the first line
+</code></pre>
+<p>Regular text.</p>
+<pre><code>code block indented by spaces
+</code></pre>
+<p>Regular text.</p>
+<pre><code>the lines in this block
+all contain trailing spaces
+</code></pre>
+<p>Regular Text.</p>
+<pre><code>code block on the last line
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_rules is test do
+               var md = """
+Dashes:
+
+---
+
+ ---
+
+  ---
+
+   ---
+
+       ---
+
+- - -
+
+ - - -
+
+  - - -
+
+   - - -
+
+       - - -
+
+
+Asterisks:
+
+***
+
+ ***
+
+  ***
+
+   ***
+
+       ***
+
+* * *
+
+ * * *
+
+  * * *
+
+   * * *
+
+       * * *
+
+
+Underscores:
+
+___
+
+ ___
+
+  ___
+
+   ___
+
+    ___
+
+_ _ _
+
+ _ _ _
+
+  _ _ _
+
+   _ _ _
+
+    _ _ _
+"""
+
+               var html = """
+<p>Dashes:</p>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>---
+</code></pre>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>- - -
+</code></pre>
+<p>Asterisks:</p>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>***
+</code></pre>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>* * *
+</code></pre>
+<p>Underscores:</p>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>___
+</code></pre>
+<hr />
+<hr />
+<hr />
+<hr />
+<pre><code>_ _ _
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_code_spans is test do
+               var md = """
+`<test a="` content of attribute `">`
+
+Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span>
+
+Here's how you put `` `backticks` `` in a code span.
+"""
+
+               var html = """
+<p><code>&lt;test a=&quot;</code> content of attribute <code>&quot;&gt;</code></p>
+<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>
+<p>Here's how you put <code>`backticks`</code> in a code span.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_images is test do
+               var md = """
+![Alt text](/path/to/img.jpg)
+
+![Alt text](/path/to/img.jpg "Optional title")
+
+Inline within a paragraph: [alt text](/url/).
+
+![alt text](/url/  "title preceded by two spaces")
+
+![alt text](/url/  "title has spaces afterward"  )
+
+![alt text](</url/>)
+
+![alt text](</url/> "with a title").
+
+![Empty]()
+
+![this is a stupid URL](http://example.com/(parens).jpg)
+
+
+![alt text][foo]
+
+  [foo]: /url/
+
+![alt text][bar]
+
+  [bar]: /url/ "Title here"
+"""
+
+               var html = """
+<p><img src="/path/to/img.jpg" alt="Alt text" /></p>
+<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
+<p>Inline within a paragraph: <a href="/url/">alt text</a>.</p>
+<p><img src="/url/" alt="alt text" title="title preceded by two spaces" /></p>
+<p><img src="/url/" alt="alt text" title="title has spaces afterward" /></p>
+<p><img src="/url/" alt="alt text" /></p>
+<p><img src="/url/" alt="alt text" title="with a title" />.</p>
+<p><img src="" alt="Empty" /></p>
+<p><img src="http://example.com/(parens).jpg" alt="this is a stupid URL" /></p>
+<p><img src="/url/" alt="alt text" /></p>
+<p><img src="/url/" alt="alt text" title="Title here" /></p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_links1 is test do
+               var md = """
+Just a [URL](/url/).
+
+[URL and title](/url/ "title").
+
+[URL and title](/url/  "title preceded by two spaces").
+
+[URL and title](/url/  "title preceded by a tab").
+
+[URL and title](/url/ "title has spaces afterward"  ).
+
+[URL wrapped in angle brackets](</url/>).
+
+[URL w/ angle brackets + title](</url/> "Here's the title").
+
+[Empty]().
+
+[With parens in the URL](http://en.wikipedia.org/wiki/WIMP_(computing))
+
+(With outer parens and [parens in url](/foo(bar)))
+
+
+[With parens in the URL](/foo(bar) "and a title")
+
+(With outer parens and [parens in url](/foo(bar) "and a title"))
+"""
+
+               var html = """
+<p>Just a <a href="/url/">URL</a>.</p>
+<p><a href="/url/" title="title">URL and title</a>.</p>
+<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>
+<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>
+<p><a href="/url/" title="title has spaces afterward">URL and title</a>.</p>
+<p><a href="/url/">URL wrapped in angle brackets</a>.</p>
+<p><a href="/url/" title="Here's the title">URL w/ angle brackets + title</a>.</p>
+<p><a href="">Empty</a>.</p>
+<p><a href="http://en.wikipedia.org/wiki/WIMP_(computing)">With parens in the URL</a></p>
+<p>(With outer parens and <a href="/foo(bar)">parens in url</a>)</p>
+<p><a href="/foo(bar)" title="and a title">With parens in the URL</a></p>
+<p>(With outer parens and <a href="/foo(bar)" title="and a title">parens in url</a>)</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_links2 is test do
+               var md = """
+Foo [bar][1].
+
+ Foo [bar][1].
+
+  Foo [bar][1].
+
+[1]: /url/  "Title"
+
+
+With [embedded [brackets]][b].
+
+
+ Indented [once][].
+
+  Indented [twice][].
+
+   Indented [thrice][].
+
+    Indented [four][] times.
+
+ [once]: /url
+
+  [twice]: /url
+
+   [thrice]: /url
+
+    [four]: /url
+
+
+[b]: /url/
+
+* * *
+
+[this][this] should work
+
+So should [this][this].
+
+And [this][].
+
+And [this][].
+
+And [this].
+
+But not [that][].
+
+Nor [that][].
+
+Nor [that].
+
+[Something in brackets like [this][] should work]
+
+[Same with [this].]
+
+In this case, [this](/somethingelse/) points to something else.
+
+Backslashing should suppress \\\[this] and [this\\\].
+
+[this]: foo
+
+
+* * *
+
+Here's one where the [link
+breaks] across lines.
+
+Here's another where the [link
+breaks] across lines, but with a line-ending space.
+
+
+[link breaks]: /url/
+"""
+
+               var html = """
+<p>Foo <a href="/url/" title="Title">bar</a>.</p>
+<p>Foo <a href="/url/" title="Title">bar</a>.</p>
+<p>Foo <a href="/url/" title="Title">bar</a>.</p>
+<p>With <a href="/url/">embedded [brackets]</a>.</p>
+<p>Indented <a href="/url">once</a>.</p>
+<p>Indented <a href="/url">twice</a>.</p>
+<p>Indented <a href="/url">thrice</a>.</p>
+<pre><code>Indented [four][] times.
+</code></pre>
+<pre><code>[four]: /url
+</code></pre>
+<hr />
+<p><a href="foo">this</a> should work</p>
+<p>So should <a href="foo">this</a>.</p>
+<p>And <a href="foo">this</a>.</p>
+<p>And <a href="foo">this</a>.</p>
+<p>And <a href="foo">this</a>.</p>
+<p>But not [that][].</p>
+<p>Nor [that][].</p>
+<p>Nor [that].</p>
+<p>[Something in brackets like <a href="foo">this</a> should work]</p>
+<p>[Same with <a href="foo">this</a>.]</p>
+<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p>
+<p>Backslashing should suppress [this] and [this].</p>
+<hr />
+<p>Here's one where the <a href="/url/">link
+breaks</a> across lines.</p>
+<p>Here's another where the <a href="/url/">link
+breaks</a> across lines, but with a line-ending space.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_links3 is test do
+               var md = """
+This is the [simple case].
+
+[simple case]: /simple
+
+
+
+This one has a [line
+break].
+
+This one has a [line
+break] with a line-ending space.
+
+[line break]: /foo
+
+
+[this][that] and the [other]
+
+[this]: /this
+[that]: /that
+[other]: /other
+"""
+
+               var html = """
+<p>This is the <a href="/simple">simple case</a>.</p>
+<p>This one has a <a href="/foo">line
+break</a>.</p>
+<p>This one has a <a href="/foo">line
+break</a> with a line-ending space.</p>
+<p><a href="/that">this</a> and the <a href="/other">other</a></p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_nested is test do
+               var md = """
+> foo
+>
+> > bar
+>
+> foo
+"""
+
+               var html = """
+<blockquote>
+<p>foo</p>
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>foo</p>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_tidyness is test do
+               var md = """
+> A list within a blockquote:
+>
+> *    asterisk 1
+> *    asterisk 2
+> *    asterisk 3
+"""
+
+       var html = """
+<blockquote>
+<p>A list within a blockquote:</p>
+<ul>
+<li>asterisk 1</li>
+<li>asterisk 2</li>
+<li>asterisk 3</li>
+</ul>
+</blockquote>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_list is test do
+               var md = """
+## Unordered
+
+Asterisks tight:
+
+*      asterisk 1
+*      asterisk 2
+*      asterisk 3
+
+
+Asterisks loose:
+
+*      asterisk 1
+
+*      asterisk 2
+
+*      asterisk 3
+
+* * *
+
+Pluses tight:
+
++      Plus 1
++      Plus 2
++      Plus 3
+
+
+Pluses loose:
+
++      Plus 1
+
++      Plus 2
+
++      Plus 3
+
+* * *
+
+
+Minuses tight:
+
+-      Minus 1
+-      Minus 2
+-      Minus 3
+
+
+Minuses loose:
+
+-      Minus 1
+
+-      Minus 2
+
+-      Minus 3
+
+
+## Ordered
+
+Tight:
+
+1.     First
+2.     Second
+3.     Third
+
+and:
+
+1. One
+2. Two
+3. Three
+
+
+Loose using tabs:
+
+1.     First
+
+2.     Second
+
+3.     Third
+
+and using spaces:
+
+1. One
+
+2. Two
+
+3. Three
+
+Multiple paragraphs:
+
+1.     Item 1, graf one.
+
+       Item 2. graf two. The quick brown fox jumped over the lazy dog's
+       back.
+
+2.     Item 2.
+
+3.     Item 3.
+
+
+
+## Nested
+
+*      Tab
+       *       Tab
+               *       Tab
+
+Here's another:
+
+1. First
+2. Second:
+       * Fee
+       * Fie
+       * Foe
+3. Third
+
+Same thing but with paragraphs:
+
+1. First
+
+2. Second:
+       * Fee
+       * Fie
+       * Foe
+
+3. Third
+"""
+
+               var html = """
+<h2>Unordered</h2>
+<p>Asterisks tight:</p>
+<ul>
+<li>asterisk 1</li>
+<li>asterisk 2</li>
+<li>asterisk 3</li>
+</ul>
+<p>Asterisks loose:</p>
+<ul>
+<li>
+<p>asterisk 1</p>
+</li>
+<li>
+<p>asterisk 2</p>
+</li>
+<li>
+<p>asterisk 3</p>
+</li>
+</ul>
+<hr />
+<p>Pluses tight:</p>
+<ul>
+<li>Plus 1</li>
+<li>Plus 2</li>
+<li>Plus 3</li>
+</ul>
+<p>Pluses loose:</p>
+<ul>
+<li>
+<p>Plus 1</p>
+</li>
+<li>
+<p>Plus 2</p>
+</li>
+<li>
+<p>Plus 3</p>
+</li>
+</ul>
+<hr />
+<p>Minuses tight:</p>
+<ul>
+<li>Minus 1</li>
+<li>Minus 2</li>
+<li>Minus 3</li>
+</ul>
+<p>Minuses loose:</p>
+<ul>
+<li>
+<p>Minus 1</p>
+</li>
+<li>
+<p>Minus 2</p>
+</li>
+<li>
+<p>Minus 3</p>
+</li>
+</ul>
+<h2>Ordered</h2>
+<p>Tight:</p>
+<ol>
+<li>First</li>
+<li>Second</li>
+<li>Third</li>
+</ol>
+<p>and:</p>
+<ol>
+<li>One</li>
+<li>Two</li>
+<li>Three</li>
+</ol>
+<p>Loose using tabs:</p>
+<ol>
+<li>
+<p>First</p>
+</li>
+<li>
+<p>Second</p>
+</li>
+<li>
+<p>Third</p>
+</li>
+</ol>
+<p>and using spaces:</p>
+<ol>
+<li>
+<p>One</p>
+</li>
+<li>
+<p>Two</p>
+</li>
+<li>
+<p>Three</p>
+</li>
+</ol>
+<p>Multiple paragraphs:</p>
+<ol>
+<li>
+<p>Item 1, graf one.</p>
+<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's
+back.</p>
+</li>
+<li>
+<p>Item 2.</p>
+</li>
+<li>
+<p>Item 3.</p>
+</li>
+</ol>
+<h2>Nested</h2>
+<ul>
+<li>Tab
+<ul>
+<li>Tab
+<ul>
+<li>Tab</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<p>Here's another:</p>
+<ol>
+<li>First</li>
+<li>Second:
+<ul>
+<li>Fee</li>
+<li>Fie</li>
+<li>Foe</li>
+</ul>
+</li>
+<li>Third</li>
+</ol>
+<p>Same thing but with paragraphs:</p>
+<ol>
+<li>
+<p>First</p>
+</li>
+<li>
+<p>Second:</p>
+<ul>
+<li>Fee</li>
+<li>Fie</li>
+<li>Foe</li>
+</ul>
+</li>
+<li>
+<p>Third</p>
+</li>
+</ol>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_strong_em is test do
+               var md = """
+***This is strong and em.***
+
+So is ***this*** word.
+
+___This is strong and em.___
+
+So is ___this___ word.
+"""
+
+               var html = """
+<p><em><strong>This is strong and em.</strong></em></p>
+<p>So is <em><strong>this</strong></em> word.</p>
+<p><em><strong>This is strong and em.</strong></em></p>
+<p>So is <em><strong>this</strong></em> word.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_tabs is test do
+               var md = """
++      this is a list item
+       indented with tabs
+
++   this is a list item
+    indented with spaces
+
+Code:
+
+       this code block is indented by one tab
+
+And:
+
+               this code block is indented by two tabs
+
+And:
+
+       +       this is an example list item
+               indented with tabs
+
+       +   this is an example list item
+           indented with spaces
+"""
+
+               var html = """
+<ul>
+<li>
+<p>this is a list item
+indented with tabs</p>
+</li>
+<li>
+<p>this is a list item
+indented with spaces</p>
+</li>
+</ul>
+<p>Code:</p>
+<pre><code>this code block is indented by one tab
+</code></pre>
+<p>And:</p>
+<pre><code>    this code block is indented by two tabs
+</code></pre>
+<p>And:</p>
+<pre><code>+   this is an example list item
+       indented with tabs
+
++   this is an example list item
+    indented with spaces
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_inline_html1 is test do
+               var md = """
+Here's a simple block:
+
+<div>
+       foo
+</div>
+
+This should be a code block, though:
+
+       <div>
+               foo
+       </div>
+
+As should this:
+
+       <div>foo</div>
+
+Now, nested:
+
+<div>
+       <div>
+               <div>
+                       foo
+               </div>
+       </div>
+</div>
+
+This should just be an HTML comment:
+
+<!-- Comment -->
+
+Multiline:
+
+<!--
+Blah
+Blah
+-->
+
+Code block:
+
+       <!-- Comment -->
+
+Just plain comment, with trailing spaces on the line:
+
+<!-- foo -->
+
+Code:
+
+       <hr />
+
+Hr's:
+
+<hr>
+
+<hr />
+
+<hr />
+
+<hr>
+
+<hr />
+
+<hr />
+
+<hr class="foo" />
+
+<hr class="foo"/>
+
+<hr class="foo" >
+"""
+
+               var html = """
+<p>Here's a simple block:</p>
+<div>
+       foo
+</div>
+<p>This should be a code block, though:</p>
+<pre><code>&lt;div&gt;
+       foo
+&lt;/div&gt;
+</code></pre>
+<p>As should this:</p>
+<pre><code>&lt;div&gt;foo&lt;/div&gt;
+</code></pre>
+<p>Now, nested:</p>
+<div>
+       <div>
+               <div>
+                       foo
+               </div>
+       </div>
+</div>
+<p>This should just be an HTML comment:</p>
+<!-- Comment -->
+<p>Multiline:</p>
+<!--
+Blah
+Blah
+-->
+<p>Code block:</p>
+<pre><code>&lt;!-- Comment --&gt;
+</code></pre>
+<p>Just plain comment, with trailing spaces on the line:</p>
+<!-- foo -->
+<p>Code:</p>
+<pre><code>&lt;hr /&gt;
+</code></pre>
+<p>Hr's:</p>
+<hr>
+<hr />
+<hr />
+<hr>
+<hr />
+<hr />
+<hr class="foo" />
+<hr class="foo"/>
+<hr class="foo" >
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_inline_html2 is test do
+               var md = """
+Simple block on one line:
+
+<div>foo</div>
+
+And nested without indentation:
+
+<div>
+<div>
+<div>
+foo
+</div>
+<div style=">"/>
+</div>
+<div>bar</div>
+</div>
+
+And with attributes:
+
+<div>
+       <div>
+       </div>
+</div>
+
+This was broken in 1.0.2b7:
+
+<div class="inlinepage">
+<div class="toggleableend">
+foo
+</div>
+</div>
+"""
+
+               var html = """
+<p>Simple block on one line:</p>
+<div>foo</div>
+<p>And nested without indentation:</p>
+<div>
+<div>
+<div>
+foo
+</div>
+<div style=">"/>
+</div>
+<div>bar</div>
+</div>
+<p>And with attributes:</p>
+<div>
+       <div>
+       </div>
+</div>
+<p>This was broken in 1.0.2b7:</p>
+<div class="inlinepage">
+<div class="toggleableend">
+foo
+</div>
+</div>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_daring_inline_html3 is test do
+               var md = """
+Paragraph one.
+
+<!-- This is a simple comment -->
+
+<!--
+       This is another comment.
+-->
+
+Paragraph two.
+
+<!-- one comment block -- -- with two comments -->
+
+The end.
+"""
+
+               var html = """
+<p>Paragraph one.</p>
+<!-- This is a simple comment -->
+<!--
+       This is another comment.
+-->
+<p>Paragraph two.</p>
+<!-- one comment block -- -- with two comments -->
+<p>The end.</p>
+"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_github.nit b/lib/markdown2/tests/test_markdown_github.nit
new file mode 100644 (file)
index 0000000..04c04a4
--- /dev/null
@@ -0,0 +1,313 @@
+# 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.
+
+# Tests for markdown Github mode
+module test_markdown_github is test
+
+import test_markdown
+import test_markdown_location
+import test_markdown_md
+import test_markdown_man
+import test_markdown_latex
+
+redef class TestMarkdown
+       redef var md_parser is lazy do
+               var parser = super
+               parser.github_mode = true
+               return parser
+       end
+end
+
+class TestGithubLocation
+       super TestMarkdownLocation
+       test
+
+       fun test_github_strike is test do
+               var md = """
+A ~striked~ text.
+"""
+               var loc = """
+MdDocument: 1,1--1,17
+  MdParagraph: 1,1--1,17
+    MdText: 1,1--1,2
+    MdStrike: 1,3--1,11
+      MdText: 1,4--1,10
+    MdText: 1,12--1,17
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_github_strike2 is test do
+               var md = """
+A ~~striked~~ text.
+"""
+               var loc = """
+MdDocument: 1,1--1,19
+  MdParagraph: 1,1--1,19
+    MdText: 1,1--1,2
+    MdStrike: 1,3--1,13
+      MdText: 1,5--1,11
+    MdText: 1,14--1,19
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_github_super is test do
+               var md = """
+A ^supered^ text.
+"""
+               var loc = """
+MdDocument: 1,1--1,17
+  MdParagraph: 1,1--1,17
+    MdText: 1,1--1,2
+    MdSuper: 1,3--1,11
+      MdText: 1,4--1,10
+    MdText: 1,12--1,17
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_github_super2 is test do
+               var md = """
+A ^^supered^^ text.
+"""
+               var loc = """
+MdDocument: 1,1--1,19
+  MdParagraph: 1,1--1,19
+    MdText: 1,1--1,2
+    MdSuper: 1,3--1,13
+      MdText: 1,5--1,11
+    MdText: 1,14--1,19
+"""
+               assert md_to_loc(md) == loc
+       end
+end
+
+class TestGithubHtml
+       super TestMarkdownHtml
+       test
+
+       fun test_strike1 is test do
+               var md = """foo ~bar~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike2 is test do
+               var md = """foo ~~bar~~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike3 is test do
+               var md = """foo ~~~bar~~~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike4 is test do
+               var md = """foo ~~~~bar~~~~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike5 is test do
+               var md = """foo ~~~~~bar~~~~~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike6 is test do
+               var md = """foo ~~~~~~bar~~~~~~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad is test do
+               var md = """foo ~bar baz\n"""
+               var html = """<p>foo ~bar baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad2 is test do
+               var md = """foo ~~bar~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad3 is test do
+               var md = """foo ~~~bar~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad4 is test do
+               var md = """foo ~~~~bar~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad5 is test do
+               var md = """foo ~~~~~bar~ baz\n"""
+               var html = """<p>foo <del>bar</del> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad6 is test do
+               var md = """foo bar~ baz\n"""
+               var html = """<p>foo bar~ baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_strike_bad7 is test do
+               var md = """foo ~bar~~~~ baz\n"""
+               var html = """<p>foo <del>bar</del>~~~ baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super1 is test do
+               var md = """foo ^bar^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super2 is test do
+               var md = """foo ^^bar^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super3 is test do
+               var md = """foo ^^^bar^^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super4 is test do
+               var md = """foo ^^^^bar^^^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super5 is test do
+               var md = """foo ^^^^^bar^^^^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super6 is test do
+               var md = """foo ^^^^^^bar^^^^^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad1 is test do
+               var md = """foo ^bar baz\n"""
+               var html = """<p>foo ^bar baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad is test do
+               var md = """foo ^^bar^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad3 is test do
+               var md = """foo ^^^bar^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad4 is test do
+               var md = """foo ^^^^bar^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad5 is test do
+               var md = """foo ^^^^^bar^ baz\n"""
+               var html = """<p>foo <sup>bar</sup> baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad6 is test do
+               var md = """foo bar^ baz\n"""
+               var html = """<p>foo bar^ baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_super_bad7 is test do
+               var md = """foo ^bar^^^^ baz\n"""
+               var html = """<p>foo <sup>bar</sup>^^^ baz</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
+
+class TestGithubMd
+       super TestMarkdownMd
+       test
+
+       fun test_strike_md is test do
+               var md = """~~foo~~\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test_super_md is test do
+               var md = """^^foo^^\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestGithubMan
+       super TestMarkdownMan
+       test
+
+       fun test_strike_man is test do
+               var md = """~~foo~~\n"""
+               var man = """\n[STRIKEOUT:foo]\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_super_man is test do
+               var md = """^foo^\n"""
+               var man = """\nfoo\n"""
+               assert md_to_man(md) == man
+       end
+end
+
+class TestGithubLatex
+       super TestMarkdownLatex
+       test
+
+       fun test_strike_latex is test do
+               var md = """
+A ~~super~~ text.
+"""
+               var tex = """
+A \\sout{super} text.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_super_latex is test do
+               var md = """
+A ^super^ text.
+"""
+               var tex = """
+A \\textsuperscript{super} text.
+"""
+               assert md_to_tex(md) == tex
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_headings_id.nit b/lib/markdown2/tests/test_markdown_headings_id.nit
new file mode 100644 (file)
index 0000000..28f91a3
--- /dev/null
@@ -0,0 +1,61 @@
+# 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.
+
+# Test for markdown headings id generation
+module test_markdown_headings_id is test
+
+import test_markdown
+
+class TestMarkdownHeadingsId
+       super TestMarkdownHtml
+       test
+
+       redef var html_renderer = new HtmlRenderer(true)
+
+       fun test_multiple_ids is test do
+               var md = """# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n"""
+               var html = """<h1 id="foo">foo</h1>\n<h2 id="foo_1">foo</h2>\n<h3 id="foo_2">foo</h3>\n<h4 id="foo_3">foo</h4>\n<h5 id="foo_4">foo</h5>\n<h6 id="foo_5">foo</h6>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_escape_ids is test do
+               var md = """# foo *bar* \\*baz\\*\n"""
+               var html = """<h1 id="foo_bar_baz">foo <em>bar</em> *baz*</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_escape_ids2 is test do
+               var md = """# foo#\n"""
+               var html = """<h1 id="foo">foo#</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_avoid_spaces is test do
+               var md = """#                  foo                     \n"""
+               var html = """<h1 id="foo">foo</h1>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_remove_atx_trailing is test do
+               var md = """## foo ##\n  ###   bar    ###\n"""
+               var html = """<h2 id="foo">foo</h2>\n<h3 id="bar">bar</h3>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_avoid_escaped_chars is test do
+               var md = """### foo \\###\n## foo #\\##\n# foo \\#\n"""
+               var html = """<h3 id="foo_">foo ###</h3>\n<h2 id="foo__1">foo ###</h2>\n<h1 id="foo__2">foo #</h1>\n"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_inlines.nit b/lib/markdown2/tests/test_markdown_inlines.nit
new file mode 100644 (file)
index 0000000..6a21084
--- /dev/null
@@ -0,0 +1,335 @@
+# 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 htmlress or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Tests for markdown inline constructs
+module test_markdown_inlines is test
+
+import test_markdown
+
+class TestMarkdownInlines
+       super TestMarkdownHtml
+       test
+
+       fun test_inlines_emph1 is test do
+               var md = """
+*single asterisks*
+
+_single underscores_
+
+**double asterisks**
+
+__double underscores__
+"""
+               var html = """<p><em>single asterisks</em></p>
+<p><em>single underscores</em></p>
+<p><strong>double asterisks</strong></p>
+<p><strong>double underscores</strong></p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_emph2 is test do
+               var md = "un*frigging*believable"
+               var html = "<p>un<em>frigging</em>believable</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_emph3 is test do
+               var md = "Con _cat_ this"
+               var html = "<p>Con <em>cat</em> this</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_emph_ext is test do
+               var md = "Con_cat_this"
+               var html = "<p>Con_cat_this</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_xml1 is test do
+               var md = """
+This is a regular paragraph.
+
+<table>
+    <tr>
+        <td>Foo</td>
+    </tr>
+</table>
+
+This is another regular paragraph.
+"""
+               var html = """
+<p>This is a regular paragraph.</p>
+<table>
+    <tr>
+        <td>Foo</td>
+    </tr>
+</table>
+<p>This is another regular paragraph.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_xml2 is test do
+               var md = """
+This is an image <img src="foo/bar" alt="baz"/> in a regular paragraph.
+"""
+               var html = """
+<p>This is an image <img src="foo/bar" alt="baz"/> in a regular paragraph.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_xml3 is test do
+               var md = """
+<div style=">"/>
+"""
+               var html = """
+<div style=">"/>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_xml4 is test do
+               var md = """
+<p>This is an example of a block element that should be escaped.</p>
+<p>Idem for the second paragraph.</p>
+"""
+               assert md_to_html(md) == md
+       end
+
+       fun test_inlines_xml5 is test do
+               var md = """
+# Some more XML tests
+
+<p>This is an example of a block element that should be escaped.</p>
+<p>Idem for the second paragraph.</p>
+
+With a *md paragraph*!
+"""
+               var html = """
+<h1>Some more XML tests</h1>
+<p>This is an example of a block element that should be escaped.</p>
+<p>Idem for the second paragraph.</p>
+<p>With a <em>md paragraph</em>!</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_escape_bad_html is test do
+               var md = "-1 if < , +1 if > and 0 otherwise"
+               var html = "<p>-1 if &lt; , +1 if &gt; and 0 otherwise</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_span_code1 is test do
+               var md = "Use the `printf()` function."
+               var html = "<p>Use the <code>printf()</code> function.</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_span_code2 is test do
+               var md = "``There is a literal backtick (`) here.``"
+               var html = "<p><code>There is a literal backtick (`) here.</code></p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_span_code3 is test do
+               var md = """
+A single backtick in a code span: `` ` ``
+
+A backtick-delimited string in a code span: `` `foo` ``
+"""
+               var html = """
+<p>A single backtick in a code span: <code>`</code></p>
+<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_span_code4 is test do
+               var md = "Please don't use any `<blink>` tags."
+               var html = "<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_span_code5 is test do
+               var md = "`&#8212;` is the decimal-encoded equivalent of `&mdash;`."
+               var html = "<p><code>&amp;#8212;</code> is the decimal-encoded equivalent of <code>&amp;mdash;</code>.</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_escape1 is test do
+               var md = "\\*this text is surrounded by literal asterisks\\*"
+               var html = "<p>*this text is surrounded by literal asterisks*</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_escape2 is test do
+               var md = "1986\\. What a great season."
+               var html = "<p>1986. What a great season.</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_escape3 is test do
+               var md = "Ben & Lux"
+               var html = "<p>Ben &amp; Lux</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link1 is test do
+               var md = """
+This is [an example](http://example.com/ "Title") inline link.
+
+[This link](http://example.net/) has no title attribute.
+"""
+               var html = """<p>This is <a href="http://example.com/" title="Title">an example</a> inline link.</p>
+<p><a href="http://example.net/">This link</a> has no title attribute.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link2 is test do
+               var md = "See my [About](/about/) page for details."
+               var html = "<p>See my <a href=\"/about/\">About</a> page for details.</p>\n"
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link3 is test do
+               var md = """
+This is [an example][id] reference-style link.
+
+Some lorem ipsum
+
+[id]: http://example.com/  "Optional Title Here"
+
+Some other lipsum
+"""
+               var html = """
+<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.</p>
+<p>Some lorem ipsum</p>
+<p>Some other lipsum</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link4 is test do
+               var md = """
+This is multiple examples: [foo][1], [bar][2], [baz][3].
+
+[1]: http://example.com/  "Optional Title Here"
+[2]: http://example.com/  'Optional Title Here'
+[3]: http://example.com/  (Optional Title Here)
+"""
+               var html = """
+<p>This is multiple examples: <a href="http://example.com/" title="Optional Title Here">foo</a>, <a href="http://example.com/" title="Optional Title Here">bar</a>, <a href="http://example.com/" title="Optional Title Here">baz</a>.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link5 is test do
+               var md = """
+This is multiple examples: [foo][a], [bar][A], [a].
+
+[a]: http://example.com/  "Optional Title Here"
+"""
+               var html = """<p>This is multiple examples: <a href="http://example.com/" title="Optional Title Here">foo</a>, <a href="http://example.com/" title="Optional Title Here">bar</a>, <a href="http://example.com/" title="Optional Title Here">a</a>.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link6 is test do
+               var md = """
+I get 10 times more traffic from [Google][] than from [Yahoo][] or [MSN][].
+
+[Google]: http://google.com/        "Google"
+[Yahoo]: http://search.yahoo.com/   "Yahoo Search"
+[MSN]: http://search.msn.com/       "MSN Search"
+"""
+               var html = """<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link7 is test do
+               var md = """
+Visit [Daring Fireball][] for more information.
+
+[Daring Fireball]: http://daringfireball.net/
+"""
+               var html = """<p>Visit <a href="http://daringfireball.net/">Daring Fireball</a> for more information.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link8 is test do
+               var md = """
+This one has a [line
+break].
+
+This one has a [line
+break] with a line-ending space.
+
+[line break]: /foo
+"""
+               var html = """
+<p>This one has a <a href="/foo">line
+break</a>.</p>
+<p>This one has a <a href="/foo">line
+break</a> with a line-ending space.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_link9 is test do
+               var md = """
+Foo [bar][].
+
+Foo [bar](/url/ "Title with \\"quotes\\" inside").
+
+
+[bar]: /url/ "Title with \\"quotes\\" inside"
+"""
+               var html = """
+<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
+<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_img1 is test do
+               var md = """
+![Alt text](/path/to/img.jpg)
+
+![Alt text](/path/to/img.jpg "Optional title")
+"""
+               var html = """
+<p><img src="/path/to/img.jpg" alt="Alt text" /></p>
+<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
+"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_inlines_img2 is test do
+               var md = """
+![Alt text][id]
+
+[id]: url/to/image  "Optional title attribute"
+"""
+               var html = """
+<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>
+"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_issues.nit b/lib/markdown2/tests/test_markdown_issues.nit
new file mode 100644 (file)
index 0000000..c8deb1b
--- /dev/null
@@ -0,0 +1,152 @@
+# 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.
+
+# Tests related to markdown issues from the Git repo
+#
+# Fixing:
+#
+# * 1525: lib/markdown: issue with nested fences
+# * 2507: markdown: some lines are lost in verbatim blocks inside a list
+#
+# See <https://github.com/nitlang/nit/issues>.
+module test_markdown_issues is test
+
+import test_markdown
+
+class TestMarkdownIssues
+       super TestMarkdownHtml
+       test
+
+       # See <https://github.com/nitlang/nit/issues/1525>.
+       fun test_issue_1525_1 is test do
+               var md = """
+A fence within a fence
+~~~~~~
+some code:
+~~~
+some other code
+~~~
+~~~~~~
+"""
+               var html = """
+<p>A fence within a fence</p>
+<pre><code>some code:
+~~~
+some other code
+~~~
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       # See <https://github.com/nitlang/nit/issues/1525>.
+       fun test_issue_1525_2 is test do
+               var md = """
+A fence within a fence
+~~~
+some code:
+```
+some other code
+```
+~~~
+"""
+               var html = """
+<p>A fence within a fence</p>
+<pre><code>some code:
+```
+some other code
+```
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       # See <https://github.com/nitlang/nit/issues/1525>.
+       fun test_issue_1525_3 is test do
+               var md = """
+A fence within a fence
+```
+some code:
+~~~
+some other code
+~~~
+```
+"""
+               var html = """
+<p>A fence within a fence</p>
+<pre><code>some code:
+~~~
+some other code
+~~~
+</code></pre>
+"""
+               assert md_to_html(md) == html
+       end
+
+       # See <https://github.com/nitlang/nit/issues/2507>.
+       fun test_issue_2507_1 is test do
+               var md = """
+*   4 spaces, `asdf` and `tab.` are lost
+    ~~~
+    a
+    as
+    asd
+    asdf
+               tab.
+    asdfg
+    ~~~
+"""
+               var html = """
+<ul>
+<li>4 spaces, <code>asdf</code> and <code>tab.</code> are lost
+<pre><code>a
+as
+asd
+asdf
+       tab.
+asdfg
+</code></pre>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+
+       # See <https://github.com/nitlang/nit/issues/2507>.
+       fun test_issue_2507_2 is test do
+               var md = """
+* 2 spaces, `as` is lost
+
+  ~~~
+  a
+  as
+  asd
+  asdf
+  ~~~
+"""
+               var html = """
+<ul>
+<li>
+<p>2 spaces, <code>as</code> is lost</p>
+<pre><code>a
+as
+asd
+asdf
+</code></pre>
+</li>
+</ul>
+"""
+               assert md_to_html(md) == html
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_latex.nit b/lib/markdown2/tests/test_markdown_latex.nit
new file mode 100644 (file)
index 0000000..ec85616
--- /dev/null
@@ -0,0 +1,542 @@
+# 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.
+
+# Tests for markdown rendering to LaTeX
+module test_markdown_latex is test
+
+import test_markdown
+import markdown_latex_rendering
+
+# Abstract test class that defines the test methods for LaTeX rendering
+abstract class TestMarkdownLatex
+       super TestMarkdown
+
+       # LaTeX renderer used in tests
+       var tex_renderer = new LatexRenderer
+
+       # Render the `md` string as LaTeX format
+       fun md_to_tex(md: String): String do
+               var node = parse_md(md)
+               return tex_renderer.render(node)
+       end
+end
+
+class TestLatexRendering
+       super TestMarkdownLatex
+       test
+
+       fun after_test is after do
+               tex_renderer.wrap_document = false
+               tex_renderer.use_listings = false
+       end
+
+       fun test_document_wrapper is test do
+               var md = """
+This example needs a document wrapper.
+"""
+
+               var tex = """
+\\documentclass[letter,10pt]{article}
+
+\\usepackage[utf8]{inputenc}
+\\usepackage{hyperref}
+\\usepackage{graphicx}
+\\usepackage{ulem}
+
+\\begin{document}
+
+This example needs a document wrapper.
+
+\\end{document}
+"""
+               tex_renderer.wrap_document = true
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_atx_headings is test do
+               var md = """
+# Title 1
+## Title 2
+### Title 3
+#### Title 4
+##### Title 5
+###### Title 6
+"""
+               var tex = """
+\\section{Title 1}
+
+\\subsection{Title 2}
+
+\\subsubsection{Title 3}
+
+\\paragraph{Title 4}
+
+\\subparagraph{Title 5}
+
+\\textbf{Title 6}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_blockquotes is test do
+               var md = """
+> this is a
+> multiline quote
+"""
+               var tex = """
+\\begin{quote}
+  this is a
+  multiline quote
+\\end{quote}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_thematic_breaks is test do
+               var md = """
+* * *
+"""
+               var tex = """
+\\begin{center}\\rule{3in}{0.4pt}\\end{center}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_paragraphs is test do
+               var md = """
+a paragraph
+on two lines
+
+another paragraph
+"""
+               var tex = """
+a paragraph
+on two lines
+
+another paragraph
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_html_block is test do
+               var md = """
+<p>
+       <a href="url">foo</a>
+</p>
+               """
+               var tex = """
+\\begin{verbatim}
+<p>
+       <a href="url">foo</a>
+</p>
+\\end{verbatim}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_indented_code is test do
+               var md = """
+    first line
+    second line
+"""
+               var tex = """
+\\begin{verbatim}
+first line
+second line
+\\end{verbatim}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_indented_code_with_listings is test do
+               var md = """
+    first line
+    second line
+"""
+               var tex = """
+\\begin{lstlisting}
+first line
+second line
+\\end{lstlisting}
+"""
+               tex_renderer.use_listings = true
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_fenced_code is test do
+               var md = """
+~~~
+first line
+second line
+~~~
+"""
+               var tex = """
+\\begin{verbatim}
+first line
+second line
+\\end{verbatim}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_fenced_code_with_listings is test do
+               var md = """
+~~~
+first line
+second line
+~~~
+"""
+               var tex = """
+\\begin{lstlisting}
+first line
+second line
+\\end{lstlisting}
+"""
+               tex_renderer.use_listings = true
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_fenced_code_with_listings_and_language is test do
+               var md = """
+~~~c
+first line
+second line
+~~~
+"""
+               var tex = """
+\\begin{lstlisting}[language=c]
+first line
+second line
+\\end{lstlisting}
+"""
+               tex_renderer.use_listings = true
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_list_ordered is test do
+               var md = """
+1) item 1
+2) item 2
+"""
+               var tex = """
+\\begin{enumerate}
+  \\item
+    item 1
+  \\item
+    item 2
+\\end{enumerate}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_list_ordered_with_starting_number is test do
+               var md = """
+4) item 1
+5) item 2
+"""
+               var tex = """
+\\begin{enumerate}
+  \\setcounter{enumi}{4}
+  \\item
+    item 1
+  \\item
+    item 2
+\\end{enumerate}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_list_unordered is test do
+               var md = """
+* item 1
+* item 2
+"""
+               var tex = """
+\\begin{itemize}
+  \\item
+    item 1
+  \\item
+    item 2
+\\end{itemize}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_list_nested is test do
+               var md = """
+* item 1
+* item 2
+   1) item 3
+   2) item 4
+"""
+               var tex = """
+\\begin{itemize}
+  \\item
+    item 1
+  \\item
+    item 2
+    \\begin{enumerate}
+      \\item
+        item 3
+      \\item
+        item 4
+    \\end{enumerate}
+\\end{itemize}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_ordered_list_nested is test do
+               var md = """
+4) item 1
+5) item 2
+
+   4) item 3
+   5) item 4
+
+      4) item 3
+      5) item 4
+
+         4) item 3
+         5) item 4
+"""
+               var tex = """
+\\begin{enumerate}
+  \\setcounter{enumi}{4}
+  \\item
+    item 1
+  \\item
+    item 2
+    \\begin{enumerate}
+      \\setcounter{enumii}{4}
+      \\item
+        item 3
+      \\item
+        item 4
+        \\begin{enumerate}
+          \\setcounter{enumiii}{4}
+          \\item
+            item 3
+          \\item
+            item 4
+            \\begin{enumerate}
+              \\setcounter{enumiv}{4}
+              \\item
+                item 3
+              \\item
+                item 4
+            \\end{enumerate}
+        \\end{enumerate}
+    \\end{enumerate}
+\\end{enumerate}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_list_and_blockquote is test do
+               var md = """
+* item 1
+* item 2
+   > quote 1
+   > quote 2
+"""
+               var tex = """
+\\begin{itemize}
+  \\item
+    item 1
+  \\item
+    item 2
+    \\begin{quote}
+      quote 1
+      quote 2
+    \\end{quote}
+\\end{itemize}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_blockquote_and_list is test do
+               var md = """
+> line 1
+> line 2
+> * item 1
+> * item 2
+"""
+               var tex = """
+\\begin{quote}
+  line 1
+  line 2
+  \\begin{itemize}
+    \\item
+      item 1
+    \\item
+      item 2
+  \\end{itemize}
+\\end{quote}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_code is test do
+               var md = """
+An `inline code`.
+"""
+               var tex = """
+An \\texttt{inline code}.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_emphasis is test do
+               var md = """
+An *emphasis* and a **strong emphasis**.
+"""
+               var tex = """
+An \\textit{emphasis} and a \\textbf{strong emphasis}.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_autolink is test do
+               var md = """
+<http://test>
+"""
+               var tex = """
+\\url{http://test}
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_link is test do
+               var md = """
+A [link](url/).
+"""
+               var tex = """
+A \\href{url/}{link}.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_link_with_title is test do
+               var md = """
+A [link](url/ "with a title").
+"""
+               var tex = """
+A \\href{url/}{link (with a title)}.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_image is test do
+               var md = """
+![image](url/).
+"""
+               var tex = """
+\\includegraphics{url/}.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_softbreak is test do
+               var md = """
+A soft
+break.
+"""
+               var tex = """
+A soft
+break.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_hardbreak is test do
+               var md = """
+A hard\\
+break.
+"""
+               var tex = """
+A hard
+break.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_escaped is test do
+               var md = """
+An escaped \\*.
+"""
+               var tex = """
+An escaped *.
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_forbidden_chars is test do
+               var md = """
+%${_><#&}\\
+"""
+               var tex = """
+\\%\\$\\{\\_\\textgreater\\textless\\#\\&\\}\\textbackslash
+"""
+               assert md_to_tex(md) == tex
+       end
+
+       fun test_full_document is test do
+               var md = """
+# Title
+
+A paragraph.
+
+## Another title
+
+A list:
+
+1. item 1
+2. item 2
+
+A code example:
+
+    line 1
+       line 2
+
+Another paragraph.
+"""
+               var tex = """
+\\section{Title}
+
+A paragraph.
+
+\\subsection{Another title}
+
+A list:
+
+\\begin{enumerate}
+  \\item
+    item 1
+  \\item
+    item 2
+\\end{enumerate}
+
+A code example:
+
+\\begin{verbatim}
+line 1
+line 2
+\\end{verbatim}
+
+Another paragraph.
+"""
+               assert md_to_tex(md) == tex
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_location.nit b/lib/markdown2/tests/test_markdown_location.nit
new file mode 100644 (file)
index 0000000..4aaa218
--- /dev/null
@@ -0,0 +1,913 @@
+# 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.
+
+# Tests for markdown nodes location
+module test_markdown_location is test
+
+import test_markdown
+
+abstract class TestMarkdownLocation
+       super TestMarkdown
+
+       redef var md_parser do
+               var parser = super
+               parser.github_mode = true
+               parser.wikilinks_mode = true
+               return parser
+       end
+
+       fun md_to_loc(md: String): String do
+               var node = parse_md(md)
+               var v = new TestMarkdownLocationVisitor
+               v.enter_visit(node)
+               return v.buffer.to_s
+       end
+end
+
+class TestMarkdownLocationVisitor
+       super MdVisitor
+
+       var buffer = new Buffer
+       var indent = 0
+
+       fun print_loc(node: MdNode) do
+               buffer.append "{"  " * indent}{node.class_name}: {node.location}\n"
+               indent += 1
+               node.visit_all(self)
+               indent -= 1
+       end
+
+       redef fun visit(node) do print_loc(node)
+end
+
+class TestLocationOutput
+       super TestMarkdownLocation
+       test
+
+       fun test_atx_headings1 is test do
+               var md = """
+# title 1
+## title 2
+### title 3
+#### title 4
+##### title 5
+###### title 6
+"""
+               var loc = """
+MdDocument: 1,1--6,14
+  MdHeading: 1,1--1,9
+    MdText: 1,3--1,9
+  MdHeading: 2,1--2,10
+    MdText: 2,4--2,10
+  MdHeading: 3,1--3,11
+    MdText: 3,5--3,11
+  MdHeading: 4,1--4,12
+    MdText: 4,6--4,12
+  MdHeading: 5,1--5,13
+    MdText: 5,7--5,13
+  MdHeading: 6,1--6,14
+    MdText: 6,8--6,14
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_atx_headings_with_trailings is test do
+               var md = """
+# title 1 #
+## title 2 ##
+### title 3 ###
+#### title 4 ####
+##### title 5 #####
+###### title 6 ######
+"""
+               var loc = """
+MdDocument: 1,1--6,21
+  MdHeading: 1,1--1,11
+    MdText: 1,3--1,9
+  MdHeading: 2,1--2,13
+    MdText: 2,4--2,10
+  MdHeading: 3,1--3,15
+    MdText: 3,5--3,11
+  MdHeading: 4,1--4,17
+    MdText: 4,6--4,12
+  MdHeading: 5,1--5,19
+    MdText: 5,7--5,13
+  MdHeading: 6,1--6,21
+    MdText: 6,8--6,14
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_settext_headings is test do
+               var md = """
+title 1
+=======
+
+title 2
+-------
+"""
+               var loc = """
+MdDocument: 1,1--5,7
+  MdHeading: 1,1--2,7
+    MdText: 1,1--1,7
+  MdHeading: 4,1--5,7
+    MdText: 4,1--4,7
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_indented_code_spaces is test do
+               var md = """
+    some code
+
+       multi lines
+"""
+               var loc = """
+MdDocument: 1,1--3,15
+  MdIndentedCodeBlock: 1,1--3,15
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_indented_code_tabs is test do
+               var md = """
+       some code
+
+       multi lines
+"""
+               var loc = """
+MdDocument: 1,1--3,15
+  MdIndentedCodeBlock: 1,1--3,15
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_fenced_code is test do
+               var md = """
+~~~
+some code
+
+multi lines
+~~~
+"""
+               var loc = """
+MdDocument: 1,1--5,3
+  MdFencedCodeBlock: 1,1--5,3
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_thematic_breaks is test do
+               var md = """
+***
+
+* * *
+
+*      *       *
+"""
+               var loc = """
+MdDocument: 1,1--5,5
+  MdThematicBreak: 1,1--1,3
+  MdThematicBreak: 3,1--3,5
+  MdThematicBreak: 5,1--5,5
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_html_blocks1 is test do
+               var md = """
+<p><a href="foo">bar</a></p>
+
+<div>
+       <a href="foo">bar</a>
+</div><hr />
+"""
+               var loc = """
+MdDocument: 1,1--5,12
+  MdHtmlBlock: 1,1--1,28
+  MdHtmlBlock: 3,1--5,12
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_paragraph1 is test do
+               var md = """
+foo bar baz
+
+line 1
+line 2
+
+other par
+with multiple lines
+"""
+               var loc = """
+MdDocument: 1,1--7,19
+  MdParagraph: 1,1--1,11
+    MdText: 1,1--1,11
+  MdParagraph: 3,1--4,6
+    MdText: 3,1--3,6
+    MdSoftLineBreak: 3,7--3,7
+    MdText: 4,1--4,6
+  MdParagraph: 6,1--7,19
+    MdText: 6,1--6,9
+    MdSoftLineBreak: 6,10--6,10
+    MdText: 7,1--7,19
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes is test do
+               var md = """
+> foo
+> bar
+"""
+               var loc = """
+MdDocument: 1,1--2,5
+  MdBlockQuote: 1,1--2,5
+    MdParagraph: 1,3--2,5
+      MdText: 1,3--1,5
+      MdSoftLineBreak: 1,6--1,6
+      MdText: 2,3--2,5
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_nested is test do
+               var md = """
+> foo
+> > foo
+> > bar
+"""
+               var loc = """
+MdDocument: 1,1--3,7
+  MdBlockQuote: 1,1--3,7
+    MdParagraph: 1,3--1,5
+      MdText: 1,3--1,5
+    MdBlockQuote: 2,3--3,7
+      MdParagraph: 2,5--3,7
+        MdText: 2,5--2,7
+        MdSoftLineBreak: 2,8--2,8
+        MdText: 3,5--3,7
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_headings is test do
+               var md = """
+> # Title 1
+> ## Title 2 ##
+"""
+               var loc = """
+MdDocument: 1,1--2,15
+  MdBlockQuote: 1,1--2,15
+    MdHeading: 1,3--1,11
+      MdText: 1,5--1,11
+    MdHeading: 2,3--2,15
+      MdText: 2,6--2,12
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_thematic_breaks is test do
+               var md = """
+> ***
+> * * *
+"""
+               var loc = """
+MdDocument: 1,1--2,7
+  MdBlockQuote: 1,1--2,7
+    MdThematicBreak: 1,3--1,5
+    MdThematicBreak: 2,3--2,7
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_indented_code is test do
+               var md = """
+>     line 1
+>     line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,12
+  MdBlockQuote: 1,1--2,12
+    MdIndentedCodeBlock: 1,3--2,12
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_fenced_code is test do
+               var md = """
+> ~~~
+> line 1
+> line 2
+> ~~~
+"""
+               var loc = """
+MdDocument: 1,1--4,5
+  MdBlockQuote: 1,1--4,5
+    MdFencedCodeBlock: 1,3--4,5
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_blockquotes_list is test do
+               var md = """
+> * line 1
+> * line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,10
+  MdBlockQuote: 1,1--2,10
+    MdUnorderedList: 1,3--2,10
+      MdListItem: 1,3--1,10
+        MdParagraph: 1,5--1,10
+          MdText: 1,5--1,10
+      MdListItem: 2,3--2,10
+        MdParagraph: 2,5--2,10
+          MdText: 2,5--2,10
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_unordered_lists is test do
+               var md = """
+* line 1
+* line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,8
+  MdUnorderedList: 1,1--2,8
+    MdListItem: 1,1--1,8
+      MdParagraph: 1,3--1,8
+        MdText: 1,3--1,8
+    MdListItem: 2,1--2,8
+      MdParagraph: 2,3--2,8
+        MdText: 2,3--2,8
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_ordered_lists is test do
+               var md = """
+1) line 1
+2) line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,9
+  MdOrderedList: 1,1--2,9
+    MdListItem: 1,1--1,9
+      MdParagraph: 1,4--1,9
+        MdText: 1,4--1,9
+    MdListItem: 2,1--2,9
+      MdParagraph: 2,4--2,9
+        MdText: 2,4--2,9
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_headings is test do
+               var md = """
+* # Title 1
+* ## Title 2 ##
+"""
+               var loc = """
+MdDocument: 1,1--2,15
+  MdUnorderedList: 1,1--2,15
+    MdListItem: 1,1--1,11
+      MdHeading: 1,3--1,11
+        MdText: 1,5--1,11
+    MdListItem: 2,1--2,15
+      MdHeading: 2,3--2,15
+        MdText: 2,6--2,12
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_thematic_breaks is test do
+               var md = """
+- ***
+- * * *
+"""
+               var loc = """
+MdDocument: 1,1--2,7
+  MdUnorderedList: 1,1--2,7
+    MdListItem: 1,1--1,5
+      MdThematicBreak: 1,3--1,5
+    MdListItem: 2,1--2,7
+      MdThematicBreak: 2,3--2,7
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_indented_codes is test do
+               var md = """
+-     line 1
+-     line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,12
+  MdUnorderedList: 1,1--2,12
+    MdListItem: 1,1--1,12
+      MdIndentedCodeBlock: 1,3--1,12
+    MdListItem: 2,1--2,12
+      MdIndentedCodeBlock: 2,3--2,12
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_fenced_codes is test do
+               var md = """
+- ~~~
+  line 1
+  line 2
+  ~~~
+"""
+               var loc = """
+MdDocument: 1,1--4,5
+  MdUnorderedList: 1,1--4,5
+    MdListItem: 1,1--4,5
+      MdFencedCodeBlock: 1,3--4,5
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_blockquotes is test do
+               var md = """
+- > line 1
+  > line 2
+"""
+               var loc = """
+MdDocument: 1,1--2,10
+  MdUnorderedList: 1,1--2,10
+    MdListItem: 1,1--2,10
+      MdBlockQuote: 1,3--2,10
+        MdParagraph: 1,5--2,10
+          MdText: 1,5--1,10
+          MdSoftLineBreak: 1,11--1,11
+          MdText: 2,5--2,10
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_pars is test do
+               var md = """
+* line 1
+  line 2
+
+* line 3
+"""
+               var loc = """
+MdDocument: 1,1--4,8
+  MdUnorderedList: 1,1--4,8
+    MdListItem: 1,1--2,8
+      MdParagraph: 1,3--2,8
+        MdText: 1,3--1,8
+        MdSoftLineBreak: 1,9--1,9
+        MdText: 2,3--2,8
+    MdListItem: 4,1--4,8
+      MdParagraph: 4,3--4,8
+        MdText: 4,3--4,8
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_list_nested is test do
+               var md = """
+* foo
+  * foo
+  * bar
+"""
+               var loc = """
+MdDocument: 1,1--3,7
+  MdUnorderedList: 1,1--3,7
+    MdListItem: 1,1--3,7
+      MdParagraph: 1,3--1,5
+        MdText: 1,3--1,5
+      MdUnorderedList: 2,3--3,7
+        MdListItem: 2,3--2,7
+          MdParagraph: 2,5--2,7
+            MdText: 2,5--2,7
+        MdListItem: 3,3--3,7
+          MdParagraph: 3,5--3,7
+            MdText: 3,5--3,7
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis is test do
+               var md = """
+An *emphasis* and a **strong emphasis**.
+"""
+               var loc = """
+MdDocument: 1,1--1,40
+  MdParagraph: 1,1--1,40
+    MdText: 1,1--1,3
+    MdEmphasis: 1,4--1,13
+      MdText: 1,5--1,12
+    MdText: 1,14--1,20
+    MdStrongEmphasis: 1,21--1,39
+      MdText: 1,23--1,37
+    MdText: 1,40--1,40
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis_nested is test do
+               var md = """
+Another ***emphasis***.
+"""
+               var loc = """
+MdDocument: 1,1--1,23
+  MdParagraph: 1,1--1,23
+    MdText: 1,1--1,8
+    MdEmphasis: 1,9--1,22
+      MdStrongEmphasis: 1,10--1,21
+        MdText: 1,12--1,19
+    MdText: 1,23--1,23
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis_nested2 is test do
+               var md = """
+Another ****emphasis****.
+"""
+               var loc = """
+MdDocument: 1,1--1,25
+  MdParagraph: 1,1--1,25
+    MdText: 1,1--1,8
+    MdStrongEmphasis: 1,9--1,24
+      MdStrongEmphasis: 1,11--1,22
+        MdText: 1,13--1,20
+    MdText: 1,25--1,25
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis_nested3 is test do
+               var md = """
+Another *****emphasis*****.
+"""
+               var loc = """
+MdDocument: 1,1--1,27
+  MdParagraph: 1,1--1,27
+    MdText: 1,1--1,8
+    MdEmphasis: 1,9--1,26
+      MdStrongEmphasis: 1,10--1,25
+        MdStrongEmphasis: 1,12--1,23
+          MdText: 1,14--1,21
+    MdText: 1,27--1,27
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis_bad is test do
+               var md = """
+Another ___ emphasis ___.
+"""
+               var loc = """
+MdDocument: 1,1--1,25
+  MdParagraph: 1,1--1,25
+    MdText: 1,1--1,25
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_emphasis_bad2 is test do
+               var md = """
+Another **emphasis.
+"""
+               var loc = """
+MdDocument: 1,1--1,19
+  MdParagraph: 1,1--1,19
+    MdText: 1,1--1,19
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_code is test do
+               var md = """
+A `code` and another ``one``.
+"""
+               var loc = """
+MdDocument: 1,1--1,29
+  MdParagraph: 1,1--1,29
+    MdText: 1,1--1,2
+    MdCode: 1,3--1,8
+    MdText: 1,9--1,21
+    MdCode: 1,22--1,28
+    MdText: 1,29--1,29
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_code_bad is test do
+               var md = """
+A `code and another ``one``.
+"""
+               var loc = """
+MdDocument: 1,1--1,28
+  MdParagraph: 1,1--1,28
+    MdText: 1,1--1,20
+    MdCode: 1,21--1,27
+    MdText: 1,28--1,28
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_autolink is test do
+               var md = """
+An <http://autolink>.
+"""
+               var loc = """
+MdDocument: 1,1--1,21
+  MdParagraph: 1,1--1,21
+    MdText: 1,1--1,3
+    MdLink: 1,4--1,20
+      MdText: 1,5--1,19
+    MdText: 1,21--1,21
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_autolink_bad is test do
+               var md = """
+An http://autolink>.
+"""
+               var loc = """
+MdDocument: 1,1--1,20
+  MdParagraph: 1,1--1,20
+    MdText: 1,1--1,20
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_autolink_bad2 is test do
+               var md = """
+An <http://autolink.
+"""
+               var loc = """
+MdDocument: 1,1--1,20
+  MdParagraph: 1,1--1,20
+    MdText: 1,1--1,20
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_automail is test do
+               var md = """
+An <me.foo+@bar.baz>.
+"""
+               var loc = """
+MdDocument: 1,1--1,21
+  MdParagraph: 1,1--1,21
+    MdText: 1,1--1,3
+    MdLink: 1,4--1,20
+      MdText: 1,5--1,19
+    MdText: 1,21--1,21
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link is test do
+               var md = """
+A [link](url/).
+"""
+               var loc = """
+MdDocument: 1,1--1,15
+  MdParagraph: 1,1--1,15
+    MdText: 1,1--1,2
+    MdLink: 1,3--1,14
+      MdText: 1,4--1,7
+    MdText: 1,15--1,15
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_with_title is test do
+               var md = """
+A [link](url/ "title").
+"""
+               var loc = """
+MdDocument: 1,1--1,23
+  MdParagraph: 1,1--1,23
+    MdText: 1,1--1,2
+    MdLink: 1,3--1,22
+      MdText: 1,4--1,7
+    MdText: 1,23--1,23
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_with_content is test do
+               var md = """
+A [`code` link](url/).
+"""
+               var loc = """
+MdDocument: 1,1--1,22
+  MdParagraph: 1,1--1,22
+    MdText: 1,1--1,2
+    MdLink: 1,3--1,21
+      MdCode: 1,4--1,9
+      MdText: 1,10--1,14
+    MdText: 1,22--1,22
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_bad is test do
+               var md = """
+A [link](url/.
+"""
+               var loc = """
+MdDocument: 1,1--1,14
+  MdParagraph: 1,1--1,14
+    MdText: 1,1--1,14
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_image is test do
+               var md = """
+A ![img](url/).
+"""
+               var loc = """
+MdDocument: 1,1--1,15
+  MdParagraph: 1,1--1,15
+    MdText: 1,1--1,2
+    MdImage: 1,3--1,14
+      MdText: 1,5--1,7
+    MdText: 1,15--1,15
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_image_bad is test do
+               var md = """
+A ![img](url/.
+"""
+               var loc = """
+MdDocument: 1,1--1,14
+  MdParagraph: 1,1--1,14
+    MdText: 1,1--1,14
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_ref is test do
+               var md = """
+A [link][].
+
+[link]: url/
+"""
+               var loc = """
+MdDocument: 1,1--1,11
+  MdParagraph: 1,1--1,11
+    MdText: 1,1--1,2
+    MdLink: 1,3--1,10
+      MdText: 1,4--1,7
+    MdText: 1,11--1,11
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_ref2 is test do
+               var md = """
+A [foo][link].
+
+[link]: url/
+"""
+               var loc = """
+MdDocument: 1,1--1,14
+  MdParagraph: 1,1--1,14
+    MdText: 1,1--1,2
+    MdLink: 1,3--1,13
+      MdText: 1,4--1,6
+    MdText: 1,14--1,14
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_link_ref_bad is test do
+               var md = """
+A [foo][link2].
+
+[link]: url/
+"""
+               var loc = """
+MdDocument: 1,1--1,15
+  MdParagraph: 1,1--1,15
+    MdText: 1,1--1,15
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_html is test do
+               var md = """
+An <br /> break line.
+"""
+               var loc = """
+MdDocument: 1,1--1,21
+  MdParagraph: 1,1--1,21
+    MdText: 1,1--1,3
+    MdHtmlInline: 1,4--1,9
+    MdText: 1,10--1,21
+"""
+               assert md_to_loc(md) == loc
+       end
+
+
+       fun test_inline_html2 is test do
+               var md = """
+An <a href="link">*emph*</a>.
+"""
+               var loc = """
+MdDocument: 1,1--1,29
+  MdParagraph: 1,1--1,29
+    MdText: 1,1--1,3
+    MdHtmlInline: 1,4--1,18
+    MdEmphasis: 1,19--1,24
+      MdText: 1,20--1,23
+    MdHtmlInline: 1,25--1,28
+    MdText: 1,29--1,29
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_escape is test do
+               var md = """
+A text with \\"escaped chars\\".
+"""
+               var loc = """
+MdDocument: 1,1--1,30
+  MdParagraph: 1,1--1,30
+    MdText: 1,1--1,30
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_soft_break is test do
+               var md = """
+A text with
+a soft break.
+"""
+               var loc = """
+MdDocument: 1,1--2,13
+  MdParagraph: 1,1--2,13
+    MdText: 1,1--1,11
+    MdSoftLineBreak: 1,12--1,12
+    MdText: 2,1--2,13
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_soft_break2 is test do
+               var md = """A text with \na hard break.\n"""
+               var loc = """
+MdDocument: 1,1--2,13
+  MdParagraph: 1,1--2,13
+    MdText: 1,1--1,11
+    MdSoftLineBreak: 1,12--1,13
+    MdText: 2,1--2,13
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_hard_break is test do
+               var md = """
+A text with\\
+a hard break.
+"""
+               var loc = """
+MdDocument: 1,1--2,13
+  MdParagraph: 1,1--2,13
+    MdText: 1,1--1,11
+    MdHardLineBreak: 1,12--1,13
+    MdText: 2,1--2,13
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_inline_hard_break2 is test do
+               var md = """A text with  \na hard break.\n"""
+               var loc = """
+MdDocument: 1,1--2,13
+  MdParagraph: 1,1--2,13
+    MdText: 1,1--1,11
+    MdHardLineBreak: 1,12--1,14
+    MdText: 2,1--2,13
+"""
+               assert md_to_loc(md) == loc
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_man.nit b/lib/markdown2/tests/test_markdown_man.nit
new file mode 100644 (file)
index 0000000..e64dd2a
--- /dev/null
@@ -0,0 +1,386 @@
+# 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.
+
+# Tests for markdown rendering to manpage
+module test_markdown_man is test
+
+import test_markdown
+import markdown_man_rendering
+
+# Abstract test class that defines the test methods for Man rendering
+abstract class TestMarkdownMan
+       super TestMarkdown
+
+       # Man renderer used in tests
+       var man_renderer = new ManRenderer
+
+       # Render the `md` string as Manpage format
+       fun md_to_man(md: String): String do
+               var node = parse_md(md)
+               return man_renderer.render(node)
+       end
+end
+
+class TestManRendering
+       super TestMarkdownMan
+       test
+
+       fun test_headings is test do
+               var md = """# title1\n## title2\n### title3\n#### title4\n##### title5\n###### title6\n"""
+               var man = """.SH title1\n.SS title2\n.TP\ntitle3\n.TP\ntitle4\n.TP\ntitle5\n.TP\ntitle6\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_bquotes is test do
+               var md = """> line 1\n> line 2\n\n> line 3\n>line 4"""
+               var man = """.RS\nline 1\nline 2\n.RE\n.RS\nline 3\nline 4\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_breaks is test do
+               var md = """* * *"""
+               var man = """***\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_indented_code is test do
+               var md = """\tline 1\n\tline 2\n"""
+               var man = """.RS\n.nf\n\\f[C]\nline\\ 1\nline\\ 2\n\\f[]\n.fi\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_fenced_code is test do
+               var md = """~~~\nline 1\nline 2\n~~~\n"""
+               var man = """.RS\n.nf\n\\f[C]\nline\\ 1\nline\\ 2\n\\f[]\n.fi\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_escaped_code is test do
+               var md = """\tline - 1\n\tline - 2\n"""
+               var man = """.RS\n.nf\n\\f[C]\nline\\ \\-\\ 1\nline\\ \\-\\ 2\n\\f[]\n.fi\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_unordered_list is test do
+               var md = """* line 1\n* line 2\n"""
+               var man = """.RS\n.IP \\[bu] 3\nline 1\n.IP \\[bu] 3\nline 2\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_ordered_list is test do
+               var md = """2) line 1\n3) line 2\n"""
+               var man = """.RS\n.IP "2." 3\nline 1\n.IP "3." 3\nline 2\n.RE\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_paragraph is test do
+               var md = """line 1\nline 2\n\nline 3\nline 4\n"""
+               var man = """\nline 1\nline 2\n\nline 3\nline 4\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_escaped_text is test do
+               var md = """foo - bar\n"""
+               var man = """\nfoo \\- bar\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_inline_code is test do
+               var md = """`foo - bar`\n"""
+               var man = """\n\\f[C]foo\\ \\-\\ bar\\f[]\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_emphasis is test do
+               var md = """*foo*\n"""
+               var man = """\n\\f[I]foo\\f[]\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_strong_emphasis is test do
+               var md = """**foo**\n"""
+               var man = """\n\\f[B]foo\\f[]\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_link is test do
+               var md = """[foo](url "title")\n"""
+               var man = """\nfoo (url title)\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_image is test do
+               var md = """![foo](url "title")\n"""
+               var man = """\nfoo (url title)\n"""
+               assert md_to_man(md) == man
+       end
+
+       fun test_full_document is test do
+
+               var md = """
+# NAME
+
+nitdoc - generates HTML pages of API documentation from Nit source files.
+
+# SYNOPSIS
+
+nitdoc [*options*]... FILE...
+
+# DESCRIPTION
+
+`nitdoc` takes one or more modules and generate HTML pages of API documentation for these modules and their imported modules.
+
+The documentation is extracted from the comments found above the definition of modules, classes, and properties.
+
+Internally, `nitdoc` relies on the presence of the `dot` command from the [graphviz] project.
+If the dot program is not present or not found, no image of hierarchies are generated.
+See option `--no-dot`.
+
+The documentation of the Nit [standard library] is generated with this tool.
+
+  [graphviz]: http://www.graphviz.org
+  [standard library]: http://nitlanguage.org/doc/stdlib
+
+# DOCUMENTATION FORMAT
+
+The format of the documentation is a dialect of [markdown] that allows GitHub fences (`~~~`).
+
+Code blocks are interpreted as snippets of Nit programs and intended to be used as examples of code.
+When these code snippets are valid, executable and contain at least and `assert` clause, they could be automatically executed and verified.
+See `nitunit(1)` for details.
+
+  [markdown]: http://daringfireball.net/projects/markdown
+
+# OPTIONS
+
+### `-d`, `--dir`
+Output directory.
+
+Where the HTML files are generated.
+
+By default, the directory is named `doc`.
+
+### `--source`
+Format to link source code.
+
+The format string is used to generated links to some parts of the source-code.
+Use `%f` for filename, `%l` for first line, and `%L` for last line.
+
+For instance, the [standard library] use the following value to link to files in GitHub:
+
+    "https://github.com/nitlang/nit/blob/$(git rev-parse HEAD)/%f#L%l-%L"
+
+Here, the `git rev-parse HEAD` is used to link to the current snapshot revision of the file.
+
+### `--no-attributes`
+Ignore the attributes.
+
+Note: In Nit, attributes are private. Therefore, this option is only useful
+when combined with `--private`.
+
+### `--no-dot`
+Do not generate graphs with graphviz.
+
+### `--private`
+Also generate private API.
+
+## CUSTOMIZATION
+
+### `--share-dir`
+Directory containing tools assets.
+
+By default `$NIT_DIR/share/nitdoc/` is used.
+
+### `--shareurl`
+Use shareurl instead of copy shared files.
+
+By default, assets from the sharedir a copied into the output directory and referred with a relative path in the generated files.
+With this option, the assets are not copied and the given URL of path is used in the generated files to locate assets.
+
+### `--custom-title`
+Custom title for homepage.
+
+### `--custom-footer-text`
+Custom footer text.
+
+### `--custom-overview-text`
+Custom intro text for homepage.
+
+### `--custom-brand`
+Custom link to external site.
+
+## SERVICES
+
+### `--github-upstream`
+Git branch where edited commits will be pulled into (ex: user:repo:branch).
+
+### `--github-base-sha1`
+Git sha1 of base commit used to create pull request.
+
+### `--github-gitdir`
+Git working directory used to resolve path name (ex: /home/me/myproject/).
+
+### `--piwik-tracker`
+Piwik tracker URL (ex: `nitlanguage.org/piwik/`).
+
+### `--piwik-site-id`
+Piwik site ID.
+
+## TESTING
+
+### `--test`
+Print test data (metrics and structure).
+
+### `--no-render`
+Do not render HTML files.
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
+"""
+
+               var man = """
+.SH NAME
+
+nitdoc \\- generates HTML pages of API documentation from Nit source files.
+.SH SYNOPSIS
+
+nitdoc [\\f[I]options\\f[]]... FILE...
+.SH DESCRIPTION
+
+\\f[C]nitdoc\\f[] takes one or more modules and generate HTML pages of API documentation for these modules and their imported modules.
+
+The documentation is extracted from the comments found above the definition of modules, classes, and properties.
+
+Internally, \\f[C]nitdoc\\f[] relies on the presence of the \\f[C]dot\\f[] command from the graphviz (http://www.graphviz.org) project.
+If the dot program is not present or not found, no image of hierarchies are generated.
+See option \\f[C]\\-\\-no\\-dot\\f[].
+
+The documentation of the Nit standard library (http://nitlanguage.org/doc/stdlib) is generated with this tool.
+.SH DOCUMENTATION FORMAT
+
+The format of the documentation is a dialect of markdown (http://daringfireball.net/projects/markdown) that allows GitHub fences (\\f[C]~~~\\f[]).
+
+Code blocks are interpreted as snippets of Nit programs and intended to be used as examples of code.
+When these code snippets are valid, executable and contain at least and \\f[C]assert\\f[] clause, they could be automatically executed and verified.
+See \\f[C]nitunit(1)\\f[] for details.
+.SH OPTIONS
+.TP
+\\f[C]\\-d\\f[], \\f[C]\\-\\-dir\\f[]
+
+Output directory.
+
+Where the HTML files are generated.
+
+By default, the directory is named \\f[C]doc\\f[].
+.TP
+\\f[C]\\-\\-source\\f[]
+
+Format to link source code.
+
+The format string is used to generated links to some parts of the source\\-code.
+Use \\f[C]%f\\f[] for filename, \\f[C]%l\\f[] for first line, and \\f[C]%L\\f[] for last line.
+
+For instance, the standard library (http://nitlanguage.org/doc/stdlib) use the following value to link to files in GitHub:
+.RS
+.nf
+\\f[C]
+"https://github.com/nitlang/nit/blob/$(git\\ rev\\-parse\\ HEAD)/%f#L%l\\-%L"
+\\f[]
+.fi
+.RE
+
+Here, the \\f[C]git\\ rev\\-parse\\ HEAD\\f[] is used to link to the current snapshot revision of the file.
+.TP
+\\f[C]\\-\\-no\\-attributes\\f[]
+
+Ignore the attributes.
+
+Note: In Nit, attributes are private. Therefore, this option is only useful
+when combined with \\f[C]\\-\\-private\\f[].
+.TP
+\\f[C]\\-\\-no\\-dot\\f[]
+
+Do not generate graphs with graphviz.
+.TP
+\\f[C]\\-\\-private\\f[]
+
+Also generate private API.
+.SS CUSTOMIZATION
+.TP
+\\f[C]\\-\\-share\\-dir\\f[]
+
+Directory containing tools assets.
+
+By default \\f[C]$NIT_DIR/share/nitdoc/\\f[] is used.
+.TP
+\\f[C]\\-\\-shareurl\\f[]
+
+Use shareurl instead of copy shared files.
+
+By default, assets from the sharedir a copied into the output directory and referred with a relative path in the generated files.
+With this option, the assets are not copied and the given URL of path is used in the generated files to locate assets.
+.TP
+\\f[C]\\-\\-custom\\-title\\f[]
+
+Custom title for homepage.
+.TP
+\\f[C]\\-\\-custom\\-footer\\-text\\f[]
+
+Custom footer text.
+.TP
+\\f[C]\\-\\-custom\\-overview\\-text\\f[]
+
+Custom intro text for homepage.
+.TP
+\\f[C]\\-\\-custom\\-brand\\f[]
+
+Custom link to external site.
+.SS SERVICES
+.TP
+\\f[C]\\-\\-github\\-upstream\\f[]
+
+Git branch where edited commits will be pulled into (ex: user:repo:branch).
+.TP
+\\f[C]\\-\\-github\\-base\\-sha1\\f[]
+
+Git sha1 of base commit used to create pull request.
+.TP
+\\f[C]\\-\\-github\\-gitdir\\f[]
+
+Git working directory used to resolve path name (ex: /home/me/myproject/).
+.TP
+\\f[C]\\-\\-piwik\\-tracker\\f[]
+
+Piwik tracker URL (ex: \\f[C]nitlanguage.org/piwik/\\f[]).
+.TP
+\\f[C]\\-\\-piwik\\-site\\-id\\f[]
+
+Piwik site ID.
+.SS TESTING
+.TP
+\\f[C]\\-\\-test\\f[]
+
+Print test data (metrics and structure).
+.TP
+\\f[C]\\-\\-no\\-render\\f[]
+
+Do not render HTML files.
+.SH SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from http://nitlanguage.org (http://nitlanguage.org)
+"""
+               assert md_to_man(md) == man
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_md.nit b/lib/markdown2/tests/test_markdown_md.nit
new file mode 100644 (file)
index 0000000..6705a2f
--- /dev/null
@@ -0,0 +1,663 @@
+# 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.
+
+# Tests for markdown rendering to markdown
+module test_markdown_md is test
+
+import test_markdown
+import markdown_md_rendering
+
+abstract class TestMarkdownMd
+       super TestMarkdown
+
+       var md_renderer = new MarkdownRenderer
+
+       fun md_to_md(md: String): String do
+               var doc = md_parser.parse(md)
+               doc.debug
+               return md_renderer.render(doc)
+       end
+end
+
+class TestMdHeadings
+       super TestMarkdownMd
+       test
+
+       fun test_no_trailings is test do
+               var md = """# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n"""
+               var exp = """# foo\n\n## foo\n\n### foo\n\n#### foo\n\n##### foo\n\n###### foo\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test_trailings is test do
+               var md = """# foo #\n## foo ##\n### foo ###\n#### foo ####\n##### foo #####\n"""
+               var exp = """# foo #\n\n## foo ##\n\n### foo ###\n\n#### foo ####\n\n##### foo #####\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test_setext is test do
+               var md = """Foo *bar*\n=========\nFoo *bar*\n---------\n"""
+               var exp = """Foo *bar*\n=========\n\nFoo *bar*\n---------\n"""
+               assert md_to_md(md) == exp
+       end
+end
+
+class TestMdBlockQuotes
+       super TestMarkdownMd
+       test
+
+       fun test191 is test do
+               var md = """> # Foo\n> bar\n> baz\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test197 is test do
+               var md = """> foo\n---\n"""
+               var exp = """> foo\n\n---\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test198 is test do
+               var md = """> - foo\n- bar\n"""
+               var exp = """> - foo\n\n- bar\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test206 is test do
+               var md = """> foo\n> bar\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test213 is test do
+               var md = """> > > foo\n> bar\n"""
+               var exp = """> > > foo\n> > > bar\n"""
+               assert md_to_md(md) == exp
+       end
+end
+
+class TestMdLists
+       super TestMarkdownMd
+       test
+
+       fun test264 is test do
+               var md = """- foo\n- bar\n+ baz\n"""
+               var exp = """- foo\n- bar\n\n+ baz\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test265 is test do
+               var md = """1. foo\n2. bar\n3) baz\n"""
+               var exp = """1. foo\n2. bar\n\n3) baz\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test270 is test do
+               var md = """- foo\n  - bar\n    - baz\n\n      bim\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test273 is test do
+               var md = """- a\n - b\n  - c\n   - d\n  - e\n - f\n- g\n"""
+               var exp = """- a\n- b\n- c\n- d\n- e\n- f\n- g\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test274 is test do
+               var md = """1. a\n\n  2. b\n\n   3. c\n"""
+               var exp = """1. a\n\n2. b\n\n3. c\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test289 is test do
+               var md = """- a\n  - b\n  - c\n\n- d\n  - e\n  - f\n"""
+               var exp = """- a\n\n  - b\n  - c\n\n- d\n\n  - e\n  - f\n"""
+               assert md_to_md(md) == exp
+       end
+end
+
+class TestMdkListItems
+       super TestMarkdownMd
+       test
+
+       fun test217 is test do
+               var md = """1.  A paragraph\n    with two lines.\n\n        indented code\n\n    > A block quote.\n"""
+               var exp = """1. A paragraph\n   with two lines.\n\n       indented code\n\n   > A block quote.\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test219 is test do
+               var md = """- one\n\n  two\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test221 is test do
+               var md = """ -    one\n\n      two\n"""
+               var exp = """- one\n\n  two\n"""
+               assert md_to_md(md) == exp
+       end
+
+       # FIXME
+       # fun test223 is test do
+               # var md = """>>- one\n>>\n  >  > two\n"""
+               # var exp = """> > - one\n> >\n> > two\n"""
+               # assert md_to_md(md) == exp
+       # end
+
+       fun test225 is test do
+               var md = """- foo\n\n  bar\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test228 is test do
+               var md = """123456789. ok\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test230 is test do
+               var md = """0. ok\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test246 is test do
+               var md = """1. foo\n2.\n3. bar\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test254 is test do
+               var md = """  1.  A paragraph\n    with two lines.\n"""
+               var exp = """1. A paragraph\n   with two lines.\n"""
+               assert md_to_md(md) == exp
+       end
+
+       # FIXME
+       # fun test255 is test do
+               # var md = """> 1. > Blockquote\n> continued here.\n"""
+               # var exp = """> 1. > Blockquote\n     > continued here.\n"""
+               # assert md_to_md(md) == exp
+       # end
+end
+
+class TestMdFencedCodeBlocks
+       super TestMarkdownMd
+       test
+
+       fun test88 is test do
+               var md = """```\nfoo\n```\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test92 is test do
+               var md = """~~~\nfoo\n~~~\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test111 is test do
+               var md = """```ruby\ndef foo(x)\n  return 3\nend\n```\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test112 is test do
+               var md = """~~~~~~\nSome markdown:\n~~~\n**hello**\n~~~\n~~~~~~\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdIndentedCodeBlocks
+       super TestMarkdownMd
+       test
+
+       fun test75 is test do
+               var md = """    a code block\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test76 is test do
+               var md = """    a simple\n      indented code block\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test80 is test do
+               var md = """    chunk1\n\n    chunk2\n  \n \n \n    chunk3\n"""
+               assert md_to_md(md) == """    chunk1\n\n    chunk2\n\n\n\n    chunk3\n"""
+       end
+
+       fun test85 is test do
+               var md = """        foo\n    bar\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test87 is test do
+               var md = """\t\tfoo  \n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdThematicBreaks
+       super TestMarkdownMd
+       test
+
+       fun test13 is test do
+               var md = """***\n---\n___\n"""
+               var exp = """***\n\n---\n\n___\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test17 is test do
+               var md = """ ***\n  ***\n   ***\n"""
+               var exp = """***\n\n***\n\n***\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test20 is test do
+               var md = """_____________________________________\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test21 is test do
+               var md = """ - - -\n"""
+               var exp = """- - -\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test22 is test do
+               var md = """ **  * ** * ** * **\n"""
+               var exp = """**  * ** * ** * **\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test23 is test do
+               var md = """-     -      -      -\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdParagraphs
+       super TestMarkdownMd
+       test
+
+       fun test182 is test do
+               var md = """aaa\n\nbbb\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test183 is test do
+               var md = """aaa\nbbb\n\nccc\nddd\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test186 is test do
+               var md = """aaa\n             bbb\n                                       ccc\n"""
+               var exp = """aaa\nbbb\nccc\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test187 is test do
+               var md = """   aaa\nbbb\n"""
+               var exp = """aaa\nbbb\n"""
+               assert md_to_md(md) == exp
+       end
+end
+
+class TestMdHTMLBlocks
+       super TestMarkdownMd
+       test
+
+       fun test116 is test do
+               var md = """<table><tr><td>\n<pre>\n*Hello*,\n\n_world_.\n</pre>\n\n</td></tr></table>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test119 is test do
+               var md = """</div>\n*foo*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test120 is test do
+               var md = """<DIV CLASS="foo">\n\n*Markdown*\n\n</DIV>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test121 is test do
+               var md = """<div id="foo"\n  class="bar">\n</div>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test124 is test do
+               var md = """<div id="foo"\n*hi*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test137 is test do
+               var md = """<pre language="haskell"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test138 is test do
+               var md = """<script type="text/javascript">\n// JavaScript example\n\ndocument.getElementById("demo").innerHTML = "Hello JavaScript!";\n</script>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test139 is test do
+               var md = """<style\n  type="text/css">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test149 is test do
+               var md = """<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test150 is test do
+               var md = """  <!-- foo -->\n\n    <!-- foo -->\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+# Inlines
+
+class TestMdLinks
+       super TestMarkdownMd
+       test
+
+       fun test_autolink is test do
+               var md = """<http://foo.bar.baz/test?q=hello&id=22&boolean>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test_automail is test do
+               var md = """<MAILTO:FOO@BAR.BAZ>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test462 is test do
+               var md = """[link](/uri "title")\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test463 is test do
+               var md = """[link](/uri)\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test464 is test do
+               var md = """[link]()\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test467 is test do
+               var md = """[link](</my%20uri>)\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test483 is test do
+               var md = """[link](/url 'title "and" title')\n"""
+               assert md_to_md(md) == """[link](/url "title \\"and\\" title")\n"""
+       end
+
+       fun test490 is test do
+               var md = """[link *foo **bar** `#`*](/uri)\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdImages
+       super TestMarkdownMd
+       test
+
+       fun test546 is test do
+               var md = """![foo](/url "title")\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test552 is test do
+               var md = """![foo](train.jpg)\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test554 is test do
+               var md = """![foo](<url>)\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test555 is test do
+               var md = """![foo](train.jpg)\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdCodeSpans
+       super TestMarkdownMd
+       test
+
+       fun test316 is test do
+               var md = """`foo`\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test319 is test do
+               var md = """``foo``\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test332 is test do
+               var md = """`foo``bar``\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdEmphasisAndStrongEmphasis
+       super TestMarkdownMd
+       test
+
+       fun test333 is test do
+               var md = """*foo bar*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test335 is test do
+               var md = """a*"foo"*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test336 is test do
+               var md = """* a *\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test351 is test do
+               var md = """*(*foo*)*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test360 is test do
+               var md = """**foo bar**\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test361 is test do
+               var md = """** foo bar**\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test364 is test do
+               var md = """__foo bar__\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test393 is test do
+               var md = """*foo**bar**baz*\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdLineBreaks
+       super TestMarkdownMd
+       test
+
+       fun test609 is test do
+               var md = """foo\\\nbaz\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test612 is test do
+               var md = """foo\\\n     bar\n"""
+               var exp = """foo\\\nbar\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test613 is test do
+               var md = """*foo  \nbar*\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test619 is test do
+               var md = """foo\\\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test623 is test do
+               var md = """foo\nbaz\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdRawHTML
+       super TestMarkdownMd
+       test
+
+       fun test590 is test do
+               var md = """<a foo="bar" bam = 'baz <em>"</em>'\n_boolean zoop:33=zoop:33 />\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test591 is test do
+               var md = """Foo <responsive-image src="foo.jpg" />\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test596 is test do
+               var md = """<a href='bar'title=title>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test599 is test do
+               var md = """foo <!-- this is a\ncomment - with hyphen -->\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test601 is test do
+               var md = """foo <!--> foo -->\n\nfoo <!-- foo--->\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test602 is test do
+               var md = """foo <?php echo $a; ?>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test604 is test do
+               var md = """foo <![CDATA[>&<]]>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test606 is test do
+               var md = """foo <a href="\\*">\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdTabs
+       super TestMarkdownMd
+       test
+
+       fun test1 is test do
+               var md = """\tfoo\tbaz\t\tbim\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test2 is test do
+               var md = """  \tfoo\tbaz\t\tbim\n"""
+               var exp = """    foo\tbaz\t\tbim\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test3 is test do
+               var md = """    a\ta\n    ὐ\ta\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test4 is test do
+               var md = """  - foo\n\n\tbar\n"""
+               var exp = """- foo\n\n  bar\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test8 is test do
+               var md = """    foo\n\tbar\n"""
+               var exp = """    foo\n    bar\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test9 is test do
+               var md = """ - foo\n   - bar\n\t - baz\n"""
+               var exp = """- foo\n  - bar\n    - baz\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test10 is test do
+               var md = """#\tFoo\n"""
+               var exp = """# Foo\n"""
+               assert md_to_md(md) == exp
+       end
+
+       fun test11 is test do
+               var md = """*\t*\t*\t\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestMdBackslashEscapes
+       super TestMarkdownMd
+       test
+
+       fun test292 is test do
+               var md = """\\\t\\A\\a\\ \\3\\φ\\«\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test295 is test do
+               var md = """foo\\\nbar\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test297 is test do
+               var md = """    \\[\\]\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test298 is test do
+               var md = """~~~\n\\[\\]\n~~~\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test299 is test do
+               var md = """<http://example.com?find=\\*>\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test300 is test do
+               var md = """<a href="/bar\\/)">\n"""
+               assert md_to_md(md) == md
+       end
+end
diff --git a/lib/markdown2/tests/test_markdown_wikilinks.nit b/lib/markdown2/tests/test_markdown_wikilinks.nit
new file mode 100644 (file)
index 0000000..8721e14
--- /dev/null
@@ -0,0 +1,180 @@
+# 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.
+
+# Tests for markdown Wikilinks mode
+module test_markdown_wikilinks is test
+
+import test_markdown
+import test_markdown_location
+import test_markdown_md
+import test_markdown_man
+import test_markdown_latex
+
+redef class TestMarkdown
+       redef var md_parser do
+               var parser = super
+               parser.wikilinks_mode = true
+               return parser
+       end
+end
+
+class TestWikilinksLocation
+       super TestMarkdownLocation
+       test
+
+       fun test_wikilinks1 is test do
+               var md = """
+A [[wiki link]] and text.
+"""
+               var loc = """
+MdDocument: 1,1--1,25
+  MdParagraph: 1,1--1,25
+    MdText: 1,1--1,2
+    MdWikilink: 1,3--1,15
+      MdText: 1,5--1,13
+    MdText: 1,16--1,25
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_wikilinks2 is test do
+               var md = """
+A [[wiki: link | with: more, args: end]] and text.
+"""
+               var loc = """
+MdDocument: 1,1--1,50
+  MdParagraph: 1,1--1,50
+    MdText: 1,1--1,2
+    MdWikilink: 1,3--1,40
+      MdText: 1,5--1,38
+    MdText: 1,41--1,50
+"""
+               assert md_to_loc(md) == loc
+       end
+
+end
+
+class TestWikilinksHtml
+       super TestMarkdownHtml
+       test
+
+       fun test_wikilinks1 is test do
+               var md = """[[foo]]\n"""
+               var html = """<p><wiki link="foo">foo</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks2 is test do
+               var md = """[[foo | bar baz]]\n"""
+               var html = """<p><wiki link="bar%20baz">foo</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks3 is test do
+               var md = """This is a [[link]] and this is another [[one]].\n"""
+               var html = """<p>This is a <wiki link="link">link</wiki> and this is another <wiki link="one">one</wiki>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks4 is test do
+               var md = """[[very: complex | link: with, more: options]]\n"""
+               var html = """<p><wiki link="link:%20with,%20more:%20options">very: complex</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad1 is test do
+               var md = """Not a [wikilink]].\n"""
+               var html = """<p>Not a [wikilink]].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad2 is test do
+               var md = """Not a [[wikilink].\n"""
+               var html = """<p>Not a [[wikilink].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad3 is test do
+               var md = """Not a ![[wikilink]].\n"""
+               var html = """<p>Not a ![[wikilink]].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad4 is test do
+               var md = """Not a [wikilink].\n"""
+               var html = """<p>Not a [wikilink].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link is test do
+               var md = """A standard [link](url).\n"""
+               var html = """<p>A standard <a href="url">link</a>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_image is test do
+               var md = """A standard ![image](url).\n"""
+               var html = """<p>A standard <img src="url" alt="image" />.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link_ref1 is test do
+               var md = """A standard [link definition].\n\n[link definition]: url\n"""
+               var html = """<p>A standard <a href="url">link definition</a>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link_ref2 is test do
+               var md = """[[wikilinks]] are not \n\n[[link definition]]: url\n"""
+               var html = """<p><wiki link="wikilinks">wikilinks</wiki> are not</p>\n<p><wiki link="link%20definition">link definition</wiki>: url</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
+
+class TestWikilinksMd
+       super TestMarkdownMd
+       test
+
+       fun test_wikilinks_md1 is test do
+               var md = """[[foo]]\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test_wikilinks_md2 is test do
+               var md = """[[foo: bar | baz: b, c: d]]\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestWikilinksMan
+       super TestMarkdownMan
+       test
+
+       fun test_wikilinks_man is test do
+               var md = """[[foo]]\n"""
+               var man = """\n(foo)\n"""
+               assert md_to_man(md) == man
+       end
+end
+
+class TestWikilinksLatex
+       super TestMarkdownLatex
+       test
+
+       fun test_wikilinks_latex is test do
+               var md = """[[foo]]\n"""
+               var tex = """\\texttt{foo}\n"""
+               assert md_to_tex(md) == tex
+       end
+end
index 327dbff..909b423 100644 (file)
@@ -22,12 +22,12 @@ class MsgPackExt
        serialize
 
        # Custom type code, in [0..127]
-       var typ: Byte
+       var typ: Int
 
        # Data bytes
        var data: Bytes
 
        redef fun hash do return typ.hash + data.hash*8
        redef fun ==(o) do return o isa MsgPackExt and o.typ == typ and o.data == data
-       redef fun to_s do return "<{class_name} typ: {typ}, data: {data.chexdigest}>"
+       redef fun to_s do return "<{class_name} typ: {typ.to_b}, data: {data.chexdigest}>"
 end
index 929c330..84f5f79 100644 (file)
 #
 # ~~~
 # assert 0x01u8.serialize_msgpack                   == b"\xD4\x7E\x01"
-# assert b"\xD4\x7E\x01".deserialize_msgpack == 0x01u8
+# assert b"\xD4\x7E\x01".deserialize_msgpack == 1
 # ~~~
 #
 # ## Full objects
index 3b8854a..be68898 100644 (file)
@@ -45,7 +45,7 @@ redef class Reader
                else if typ & 0b1000_0000 == 0 or typ & 0b1110_0000 == 0b1110_0000 then
                        # fixint
                        var bytes = new Bytes.with_capacity(1)
-                       bytes.add typ.to_b
+                       bytes.add typ
                        return bytes.to_i(signed=true)
 
                else if typ & 0b1111_0000 == 0b1000_0000 then
@@ -174,7 +174,7 @@ redef class Reader
        # var reader = new BytesReader(b"\xC7\x03\x0A\x0B\x0C\x0D")
        # var ext = reader.read_msgpack
        # assert ext isa MsgPackExt
-       # assert ext.typ == 0x0Au8
+       # assert ext.typ == 0x0a
        # assert ext.data == b"\x0B\x0C\x0D"
        # ~~~
        private fun read_msgpack_fixext_data(len: Int): MsgPackExt
@@ -182,7 +182,7 @@ redef class Reader
                var exttyp = read_byte
                if exttyp < 0 then exttyp = 0
                var data = read_bytes(len)
-               return new MsgPackExt(exttyp.to_b, data)
+               return new MsgPackExt(exttyp, data)
        end
 
        # Read the content of a dynamic *ext* including the length on `len_len` bytes
index a9e9ddf..edf9210 100644 (file)
@@ -19,14 +19,14 @@ module serialization_common
 abstract class MsgPackEngine
 
        # *ext type* byte for object definitions, defaults to 0x7Bu8 or '{'
-       var ext_typ_obj: Byte = 0x7Bu8 is writable
+       var ext_typ_obj: Int = 0x7B is writable
 
        # *ext type* byte for object references, defaults to 0x7Du8 or '}'
-       var ext_typ_ref: Byte = 0x7Du8 is writable
+       var ext_typ_ref: Int = 0x7D is writable
 
        # *ext type* byte to identify a char, defaults to 0x7Cu8 or '~'
-       var ext_typ_char: Byte = 0x7Cu8 is writable
+       var ext_typ_char: Int = 0x7C is writable
 
        # *ext type* byte to identify a byte, defaults to 0x7Eu8 or '|'
-       var ext_typ_byte: Byte = 0x7Eu8 is writable
+       var ext_typ_byte: Int = 0x7E is writable
 end
index 0b5b4f9..e1bb2d0 100644 (file)
@@ -266,7 +266,7 @@ redef class Byte
                else
                        # Write as ext
                        var bytes = new Bytes.with_capacity(1)
-                       bytes.add self
+                       bytes.add self.to_i
                        v.stream.write_msgpack_ext(v.ext_typ_byte, bytes)
                end
        end
index 15e5985..7d18e32 100644 (file)
@@ -20,11 +20,11 @@ import binary
 redef class Writer
 
        # Write `null`, or nil, in MessagePack format
-       fun write_msgpack_null do write_byte 0xC0u8
+       fun write_msgpack_null do write_byte 0xC0
 
        # Write `bool` in MessagePack format
        fun write_msgpack_bool(bool: Bool)
-       do write_byte(if bool then 0xC3u8 else 0xC2u8)
+       do write_byte(if bool then 0xC3 else 0xC2)
 
        # ---
        # Integers
@@ -61,7 +61,7 @@ redef class Writer
        fun write_msgpack_fixint(value: Int)
        do
                assert value >= -0x20 and value <= 0x7F
-               write_byte value.to_b
+               write_byte value
        end
 
        # Write `value` over one unsigned byte, following 1 metadata byte
@@ -69,7 +69,7 @@ redef class Writer
        # Require: `value >= 0x00 and value <= 0xFF`
        fun write_msgpack_uint8(value: Int)
        do
-               write_byte 0xCCu8
+               write_byte 0xCC
                write_bytes value.to_bytes(n_bytes=1)
        end
 
@@ -78,7 +78,7 @@ redef class Writer
        # Require: `value >= 0x00 and value <= 0xFFFF`
        fun write_msgpack_uint16(value: Int)
        do
-               write_byte 0xCDu8
+               write_byte 0xCD
                write_bytes value.to_bytes(n_bytes=2)
        end
 
@@ -87,7 +87,7 @@ redef class Writer
        # Require: `value >= 0x00 and value <= 0xFFFF_FFFF`
        fun write_msgpack_uint32(value: Int)
        do
-               write_byte 0xCEu8
+               write_byte 0xCE
                write_bytes value.to_bytes(n_bytes=4)
        end
 
@@ -96,7 +96,7 @@ redef class Writer
        # Require: `value >= 0x00 and value <= 0xFFFF_FFFF_FFFF_FFFF`
        fun write_msgpack_uint64(value: Int)
        do
-               write_byte 0xCFu8
+               write_byte 0xCF
                write_bytes value.to_bytes(n_bytes=8)
        end
 
@@ -105,28 +105,28 @@ redef class Writer
        # Require: `value >= -128  and value <= 127`
        fun write_msgpack_int8(value: Int)
        do
-               write_byte 0xD0u8
+               write_byte 0xD0
                write_bytes value.to_bytes(n_bytes=1)
        end
 
        # Write `value` over two signed bytes, following 1 metadata byte
        fun write_msgpack_int16(value: Int)
        do
-               write_byte 0xD1u8
+               write_byte 0xD1
                write_bytes value.to_bytes(n_bytes=2)
        end
 
        # Write `value` over 4 signed bytes, following 1 metadata byte
        fun write_msgpack_int32(value: Int)
        do
-               write_byte 0xD2u8
+               write_byte 0xD2
                write_bytes value.to_bytes(n_bytes=4)
        end
 
        # Write `value` over 8 signed bytes, following 1 metadata byte
        fun write_msgpack_int64(value: Int)
        do
-               write_byte 0xD3u8
+               write_byte 0xD3
                write_int64 value
        end
 
@@ -136,14 +136,14 @@ redef class Writer
        # Write `value` as a MessagePack float (losing precision)
        fun write_msgpack_float(value: Float)
        do
-               write_byte 0xCAu8
+               write_byte 0xCA
                write_float value
        end
 
        # Write `value` as a MessagePack double
        fun write_msgpack_double(value: Float)
        do
-               write_byte 0xCBu8
+               write_byte 0xCB
                write_double value
        end
 
@@ -177,7 +177,7 @@ redef class Writer
                var len = text.byte_length
                assert len <= 0x1F
 
-               var b = 0b1010_0000u8 | len.to_b
+               var b = 0b1010_0000 | len
                write_byte b
 
                write text
@@ -191,8 +191,8 @@ redef class Writer
                var len = text.byte_length
                assert len <= 0xFF
 
-               write_byte 0xD9u8
-               write_byte len.to_b
+               write_byte 0xD9
+               write_byte len
                write text
        end
 
@@ -204,10 +204,10 @@ redef class Writer
                var len = text.byte_length
                assert len <= 0xFFFF
 
-               write_byte 0xDAu8
+               write_byte 0xDA
                var len_bytes = len.to_bytes
                write_byte len_bytes[0]
-               write_byte if len_bytes.length > 1 then len_bytes[1] else 0u8
+               write_byte if len_bytes.length > 1 then len_bytes[1] else 0
                write text
        end
 
@@ -219,11 +219,11 @@ redef class Writer
                var len = text.byte_length
                assert len <= 0xFFFF_FFFF
 
-               write_byte 0xDBu8
+               write_byte 0xDB
                var len_bytes = len.to_bytes
                write_byte len_bytes[0]
                for i in [1..4[ do
-                       write_byte if len_bytes.length > i then len_bytes[i] else 0u8
+                       write_byte if len_bytes.length > i then len_bytes[i] else 0
                end
                write text
        end
@@ -254,8 +254,8 @@ redef class Writer
                var len = data.length
                assert len <= 0xFF
 
-               write_byte 0xC4u8
-               write_byte len.to_b
+               write_byte 0xC4
+               write_byte len
                write_bytes data
        end
 
@@ -267,7 +267,7 @@ redef class Writer
                var len = data.length
                assert len <= 0xFFFF
 
-               write_byte 0xC5u8
+               write_byte 0xC5
                write_bytes len.to_bytes(n_bytes=2)
                write_bytes data
        end
@@ -280,7 +280,7 @@ redef class Writer
                var len = data.length
                assert len <= 0xFFFF_FFFF
 
-               write_byte 0xC6u8
+               write_byte 0xC6
                write_bytes len.to_bytes(n_bytes=4)
                write_bytes data
        end
@@ -314,7 +314,7 @@ redef class Writer
        fun write_msgpack_fixarray(len: Int)
        do
                assert len <= 0x0F
-               write_byte 0b1001_0000u8 | len.to_b
+               write_byte 0b1001_0000 | len
        end
 
        # Write an array header for `len` items, max of 0xFFFF items
@@ -325,7 +325,7 @@ redef class Writer
        fun write_msgpack_array16(len: Int)
        do
                assert len <= 0xFFFF
-               write_byte 0xDCu8
+               write_byte 0xDC
                write_bytes len.to_bytes(n_bytes=2)
        end
 
@@ -337,7 +337,7 @@ redef class Writer
        fun write_msgpack_array32(len: Int)
        do
                assert len <= 0xFFFF_FFFF
-               write_byte 0xDDu8
+               write_byte 0xDD
                write_bytes len.to_bytes(n_bytes=4)
        end
 
@@ -372,7 +372,7 @@ redef class Writer
        fun write_msgpack_fixmap(len: Int)
        do
                assert len <= 0x0F
-               write_byte 0b1000_0000u8 | len.to_b
+               write_byte 0b1000_0000 | len
        end
 
        # Write a map header for `len` key/value pairs, max of 0xFFFF pairs
@@ -384,7 +384,7 @@ redef class Writer
        fun write_msgpack_map16(len: Int)
        do
                assert len <= 0xFFFF
-               write_byte 0xDEu8
+               write_byte 0xDE
                write_bytes len.to_bytes(n_bytes=2)
        end
 
@@ -397,7 +397,7 @@ redef class Writer
        fun write_msgpack_map32(len: Int)
        do
                assert len <= 0xFFFF_FFFF
-               write_byte 0xDFu8
+               write_byte 0xDF
                write_bytes len.to_bytes(n_bytes=4)
        end
 
@@ -410,10 +410,10 @@ redef class Writer
        #
        # ~~~
        # var writer = new BytesWriter
-       # writer.write_msgpack_ext(0x0Au8, b"\x0B\x0C\x0D")
+       # writer.write_msgpack_ext(0x0A, b"\x0B\x0C\x0D")
        # assert writer.bytes == b"\xC7\x03\x0A\x0B\x0C\x0D"
        # ~~~
-       fun write_msgpack_ext(typ: Byte, bytes: Bytes)
+       fun write_msgpack_ext(typ: Int, bytes: Bytes)
        do
                var len = bytes.length
                if len == 1 then
@@ -448,45 +448,45 @@ redef class Writer
        # Write the header for an application-specific extension of one data byte
        #
        # After writing the header, clients should write the data byte.
-       fun write_msgpack_fixext1(typ: Byte)
+       fun write_msgpack_fixext1(typ: Int)
        do
-               write_byte 0xD4u8
+               write_byte 0xD4
                write_byte typ
        end
 
        # Write the header for an application-specific extension of two data bytes
        #
        # After writing the header, clients should write the two data bytes.
-       fun write_msgpack_fixext2(typ: Byte)
+       fun write_msgpack_fixext2(typ: Int)
        do
-               write_byte 0xD5u8
+               write_byte 0xD5
                write_byte typ
        end
 
        # Write the header for an application-specific extension of 4 data bytes
        #
        # After writing the header, clients should write the 4 data bytes.
-       fun write_msgpack_fixext4(typ: Byte)
+       fun write_msgpack_fixext4(typ: Int)
        do
-               write_byte 0xD6u8
+               write_byte 0xD6
                write_byte typ
        end
 
        # Write the header for an application-specific extension of 8 data bytes
        #
        # After writing the header, clients should write the 8 data bytes.
-       fun write_msgpack_fixext8(typ: Byte)
+       fun write_msgpack_fixext8(typ: Int)
        do
-               write_byte 0xD7u8
+               write_byte 0xD7
                write_byte typ
        end
 
        # Write the header for an application-specific extension of 16 data bytes
        #
        # After writing the header, clients should write the 16 data bytes.
-       fun write_msgpack_fixext16(typ: Byte)
+       fun write_msgpack_fixext16(typ: Int)
        do
-               write_byte 0xD8u8
+               write_byte 0xD8
                write_byte typ
        end
 
@@ -495,11 +495,11 @@ redef class Writer
        # After writing the header, clients should write the data bytes.
        #
        # Require: `len >= 0 and <= 0xFF`
-       fun write_msgpack_ext8(typ: Byte, len: Int)
+       fun write_msgpack_ext8(typ, len: Int)
        do
                assert len >= 0 and len <= 0xFF
-               write_byte 0xC7u8
-               write_byte len.to_b
+               write_byte 0xC7
+               write_byte len
                write_byte typ
        end
 
@@ -508,10 +508,10 @@ redef class Writer
        # After writing the header, clients should write the data bytes.
        #
        # Require: `len >= 0 and <= 0xFFFF`
-       fun write_msgpack_ext16(typ: Byte, len: Int)
+       fun write_msgpack_ext16(typ, len: Int)
        do
                assert len >= 0 and len <= 0xFFFF
-               write_byte 0xC8u8
+               write_byte 0xC8
                write_bytes len.to_bytes(n_bytes=2)
                write_byte typ
        end
@@ -521,10 +521,10 @@ redef class Writer
        # After writing the header, clients should write the data bytes.
        #
        # Require: `len >= 0 and <= 0xFFFF_FFFF`
-       fun write_msgpack_ext32(typ: Byte, len: Int)
+       fun write_msgpack_ext32(typ, len: Int)
        do
                assert len >= 0 and len <= 0xFFFF_FFFF
-               write_byte 0xC9u8
+               write_byte 0xC9
                write_bytes len.to_bytes(n_bytes=4)
                write_byte typ
        end
index a9ef5f6..96293f6 100644 (file)
@@ -125,7 +125,7 @@ class FileServer
                if response.status_code != 200 then
                        var tmpl = error_page(response.status_code)
                        if header != null and tmpl isa ErrorTemplate then tmpl.header = header
-                       response.body = tmpl.to_s
+                       response.body = tmpl
                end
 
                return response
index ec83289..97276ca 100644 (file)
@@ -20,6 +20,7 @@
 module http_response
 
 import serialization
+private import template
 
 # A response to send over HTTP
 class HttpResponse
@@ -38,7 +39,7 @@ class HttpResponse
        var header = new HashMap[String, String]
 
        # Body of this response
-       var body = "" is writable
+       var body: Writable = "" is writable
 
        # Files appended after `body`
        var files = new Array[String]
@@ -49,7 +50,20 @@ class HttpResponse
                # Set the content length if not already set
                if not header.keys.has("Content-Length") then
                        # Size of the body
-                       var len = body.byte_length
+                       var len
+                       var body = self.body
+                       if body isa Text then
+                               len = body.byte_length
+                       else if body isa Bytes then
+                               len = body.length
+                       else
+                               # We need the length, but there is no length in a writable.
+                               # So just render it as a bytes then measure :/
+                               body = body.write_to_bytes
+                               len = body.length
+                               # Keep the body as bytes since we have it
+                               self.body = body
+                       end
 
                        # Size of included files
                        for path in files do
@@ -77,17 +91,18 @@ class HttpResponse
        end
 
        # Get this reponse as a string according to HTTP protocol
-       redef fun to_s
+       fun render: Writable
        do
                finalize
 
-               var buf = new FlatBuffer
-               buf.append("{http_version} {status_code} {status_message or else ""}\r\n")
+               var buf = new Template
+               buf.add("{http_version} {status_code} {status_message or else ""}\r\n")
                for key, value in header do
-                       buf.append("{key}: {value}\r\n")
+                       buf.add("{key}: {value}\r\n")
                end
-               buf.append("\r\n{body}")
-               return buf.to_s
+               buf.add("\r\n")
+               buf.add body
+               return buf
        end
 end
 
index afa0d0a..def3699 100644 (file)
@@ -91,7 +91,7 @@ class HttpServer
        # Send back `response` to the client
        fun respond(response: HttpResponse)
        do
-               write response.to_s
+               response.render.write_to(self)
                for path in response.files do write_file path
        end
 end
@@ -176,7 +176,7 @@ redef class Sys
 
                var listener = listeners[name, port]
                if listener == null then
-                       listener = factory.bind_to(name, port)
+                       listener = factory.bind_tcp(name, port)
                        if listener != null then
                                sys.listeners[name, port] = listener
                                listeners_count[name, port] = 1
index 31aefd6..7e55f69 100644 (file)
@@ -58,7 +58,7 @@ do
        # Fallback
        if bytes == null or bytes.length != bin_length or force_rand == true then
                bytes = new Bytes.with_capacity(bin_length)
-               for i in bin_length.times do bytes.add 256.rand.to_b
+               for i in bin_length.times do bytes.add 256.rand
        end
 
        # Encode in base64 so it is readable
index d8ab3cb..585130e 100644 (file)
@@ -101,6 +101,7 @@ class Perfecthashing
        # n : number of required free identifiers
        # idc : This array will be filled with n free identifiers
        # return the size of hashTable to create for theses identifiers (mask + 1)
+       #
        #     var ph = new Perfecthashing
        #     var idc = new Array[Int]
        #     assert ph.pnand([3, 7, 10], 1, idc) == 6
index e657d68..cd7a380 100644 (file)
@@ -431,7 +431,7 @@ redef class HttpResponse
        # Write data in body response and send it.
        fun send(raw_data: nullable Writable, status: nullable Int) do
                if raw_data != null then
-                       body += raw_data.write_to_string
+                       body = raw_data
                end
                if status != null then
                        status_code = status
diff --git a/lib/posix/README.md b/lib/posix/README.md
new file mode 100644 (file)
index 0000000..3b73f9c
--- /dev/null
@@ -0,0 +1,5 @@
+Services conforming to POSIX
+
+The core module `posix` includes POSIX services available on all POSIX compliant systems.
+For services provided by some implementations of POSIX but absent from any POSIX version,
+import `posix::ext`.
similarity index 91%
rename from lib/posix_ext/posix_ext.nit
rename to lib/posix/ext.nit
index 8dd83c3..85da40a 100644 (file)
@@ -1,7 +1,5 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
-#
 # 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
@@ -15,7 +13,9 @@
 # limitations under the License.
 
 # Services not defined in POSIX but provided by most implementations
-module posix_ext
+module ext
+
+import posix
 
 redef extern class Passwd
        # User information
similarity index 55%
rename from lib/posix_ext/package.ini
rename to lib/posix/package.ini
index 6b78527..79c6ca1 100644 (file)
@@ -1,12 +1,12 @@
 [package]
-name=posix_ext
+name=posix
 tags=wrapper,lib
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
-desc=Services not defined in POSIX but provided by most implementations
+desc=Services conforming to POSIX
 [upstream]
-browse=https://github.com/nitlang/nit/tree/master/lib/posix_ext/
+browse=https://github.com/nitlang/nit/tree/master/lib/posix/
 git=https://github.com/nitlang/nit.git
-git.directory=lib/posix_ext/
+git.directory=lib/posix/
 homepage=http://nitlanguage.org
 issues=https://github.com/nitlang/nit/issues
similarity index 94%
rename from lib/core/posix.nit
rename to lib/posix/posix.nit
index 587e606..03a8a2e 100644 (file)
@@ -1,7 +1,5 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
 # 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
@@ -17,8 +15,6 @@
 # Services conforming to POSIX
 module posix
 
-import text
-
 in "C Header" `{
 #include <sys/types.h>
 #include <unistd.h>
@@ -111,8 +107,3 @@ extern class Group `{struct group*`}
                return ret;
        `}
 end
-
-redef class Int
-       # Does the file descriptor `self` refer to a terminal?
-       fun isatty: Bool `{ return isatty(self); `}
-end
index f17a28e..c3a9466 100644 (file)
@@ -21,6 +21,7 @@
 module privileges
 
 import opts
+import posix
 
 redef class Text
        # Does the operating system know the user named `self`?
index a80e9f2..6ad30c8 100644 (file)
@@ -245,7 +245,7 @@ redef class Text
        # sha1_hexdigest.
        #
        #     import base64
-       #     assert "The quick brown fox jumps over the lazy dog".sha1 == [0x2Fu8, 0xD4u8, 0xE1u8, 0xC6u8, 0x7Au8, 0x2Du8, 0x28u8, 0xFCu8, 0xEDu8, 0x84u8, 0x9Eu8, 0xE1u8, 0xBBu8, 0x76u8, 0xE7u8, 0x39u8, 0x1Bu8, 0x93u8, 0xEBu8, 0x12u8]
+       #     assert "The quick brown fox jumps over the lazy dog".sha1 == [0x2F, 0xD4, 0xE1, 0xC6, 0x7A, 0x2D, 0x28, 0xFC, 0xED, 0x84, 0x9E, 0xE1, 0xBB, 0x76, 0xE7, 0x39, 0x1B, 0x93, 0xEB, 0x12]
        fun sha1: Bytes do
                return new Bytes(to_cstring.sha1_intern(byte_length), 20, 20)
        end
index e359b77..13b4049 100644 (file)
@@ -141,7 +141,7 @@ extern class NativeSocket `{ int* `}
        `}
 
        # Write `value` as a single byte
-       fun write_byte(value: Byte): Int `{
+       fun write_byte(value: Int): Int `{
                unsigned char byt = (unsigned char)value;
                return write(*self, &byt, 1);
        `}
index 610ec2e..447a33f 100644 (file)
@@ -36,6 +36,7 @@ import abstract_tree
 #  * delete average O(lg n) worst O(n)
 #
 # Usage:
+#
 #     var tree = new BinTreeMap[Int, String]
 #     tree[1] = "n1"
 #     assert tree.min == "n1"
diff --git a/lib/trees/bktree.nit b/lib/trees/bktree.nit
new file mode 100644 (file)
index 0000000..b7d0d48
--- /dev/null
@@ -0,0 +1,149 @@
+# 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.
+
+# Implementation of BKTree
+#
+# As proposed by W. A. Burkhard and R. M. Keller in
+# "Some approaches to best-match file searching" the BKTree data structure
+# is usefull to speed-up spell checking based on the Levenshtein distance between
+# words.
+#
+# With a BKTree, the complexity to find mispelled words in a dictionnary is *O(log n)*
+# instead of *O(n)* with a dummy list.
+#
+# Example:
+#
+# ~~~
+# # Create a new BKTree
+# var tree = new BKTree
+#
+# # Index some words in the dictionnary for spell checking
+# tree.add("book")
+# tree.add("books")
+# tree.add("cake")
+# tree.add("boo")
+# tree.add("cape")
+# tree.add("boon")
+# tree.add("cook")
+# tree.add("cart")
+#
+# # Search suggestions in the BKTree
+# assert tree.search("caqe").join(", ") == "\{1: cake\}, \{1: cape\}"
+# ~~~
+#
+# See <https://dl.acm.org/citation.cfm?id=362003.362025>.
+module bktree
+
+import abstract_tree
+
+# A BKTree implementation
+#
+# See `add` to insert a new word.
+# See `search` to find matches from a `key`.
+class BKTree
+
+       # Default tolerance used to find matches
+       #
+       # Default is `2`.
+       var default_tolerance = 2 is writable
+
+       # Tree root
+       private var root: nullable BKNode = null
+
+       # Add a `key` in the tree
+       fun add(key: String) do
+               var root = self.root
+               if root == null then
+                       self.root = new BKNode(key)
+                       return
+               end
+
+               var node = root
+               var dist = node.key.levenshtein_distance(key)
+
+               while node.has_key(dist) do
+                       if dist == 0 then return
+                       node = node[dist]
+                       dist = node.key.levenshtein_distance(key)
+               end
+               node[dist] = new BKNode(key)
+       end
+
+       # Search `key` with a distance of `tolerance` in `self`.
+       #
+       # If `tolerance` is null, the use `default_tolerance` instead.
+       fun search(key: String, tolerance: nullable Int): Array[BKMatch] do
+               var res = new Array[BKMatch]
+               var root = self.root
+               if root != null then
+                       if tolerance == null then tolerance = self.default_tolerance
+                       search_recursive(root, res, key, tolerance)
+               end
+               default_comparator.sort(res)
+               return res
+       end
+
+       private fun search_recursive(node: BKNode, res: Array[BKMatch], key: String, tolerance: Int) do
+               var dist = node.key.levenshtein_distance(key)
+               var min = dist - tolerance
+               var max = dist + tolerance
+
+               if dist < tolerance then
+                       res.add new BKMatch(dist, node.key)
+               end
+
+               for odist, child in node do
+                       if odist < min or odist > max then continue
+                       search_recursive(child, res, key, tolerance)
+               end
+       end
+end
+
+# A node that goes in a BKTree
+#
+# Each child is mapped from `self` by its distance as an Int.
+private class BKNode
+       super HashMap[Int, BKNode]
+
+       # Key stored in `self`
+       var key: String
+
+       redef fun to_s do return "\{{key}\}"
+end
+
+# A match in a BKTree
+#
+# Used to order results returned by `BKTree::search`.
+class BKMatch
+       super Comparable
+
+       redef type OTHER: BKMatch
+
+       # Distance of `key` from the search query
+       var distance: Int
+
+       # Matched `key`
+       var key: String
+
+       redef fun ==(o) do return o isa BKMatch and distance == o.distance and key == o.key
+
+       redef fun <=>(o) do
+               if distance == o.distance then
+                       return key <=> o.key
+               end
+               return distance <=> o.distance
+       end
+
+       redef fun to_s do return "\{{distance}: {key}\}"
+end
index 4a64f99..ad3d928 100644 (file)
@@ -77,6 +77,17 @@ class Vector
                return super
        end
 
+       # Increment value for `obj` term
+       #
+       # If the term isn't already in the vector, the new value is 1.0.
+       fun inc(obj: nullable Object) do
+               if has_key(obj) then
+                       self[obj] += 1.0
+               else
+                       self[obj] = 1.0
+               end
+       end
+
        # The norm of the vector.
        #
        # `||x|| = (x1 ** 2 ... + xn ** 2).sqrt`
@@ -112,10 +123,18 @@ end
 # Documents can then be matched to query vectors.
 class VSMIndex
 
+       # Kind of documents stored in this index
+       #
+       # Clients can redefine this type to specialize the index.
+       type DOC: Document
+
        # Documents index
+       var documents = new HashSet[DOC]
+
+       # Inversed index
        #
-       # TODO use a more efficient representation.
-       var documents = new HashSet[Document]
+       # Link documents to existing terms.
+       var inversed_index = new HashMap[nullable Object, Array[DOC]]
 
        # Count for all terms in all indexed documents
        #
@@ -137,12 +156,18 @@ class VSMIndex
        #
        # Returns an `IndexMatch` for each indexed document.
        # Results are ordered by descending similarity.
-       fun match_vector(query: Vector): Array[IndexMatch] do
-               var matches = new Array[IndexMatch]
+       fun match_vector(query: Vector): Array[IndexMatch[DOC]] do
+               var documents = new HashSet[DOC]
+               for term, count in query do
+                       if inversed_index.has_key(term) then
+                               documents.add_all inversed_index[term]
+                       end
+               end
+               var matches = new Array[IndexMatch[DOC]]
                for doc in documents do
                        var sim = query.cosine_similarity(doc.tfidf)
                        if sim == 0.0 then continue
-                       matches.add new IndexMatch(doc, sim)
+                       matches.add new IndexMatch[DOC](doc, sim)
                end
                sorter.sort(matches)
                return matches
@@ -156,13 +181,13 @@ class VSMIndex
        #
        # When processing batch documents, use `auto_update = false` to disable
        # the auto update of the index.
-       fun index_document(doc: Document, auto_update: nullable Bool) do
+       fun index_document(doc: DOC, auto_update: nullable Bool) do
                for term, count in doc.terms_count do
-                       if not terms_doc_count.has_key(term) then
-                               terms_doc_count[term] = 1.0
-                       else
-                               terms_doc_count[term] += 1.0
+                       terms_doc_count.inc(term)
+                       if not inversed_index.has_key(term) then
+                               inversed_index[term] = new Array[DOC]
                        end
+                       inversed_index[term].add doc
                end
                documents.add doc
                if auto_update == null or auto_update then update_index
@@ -196,7 +221,7 @@ class StringIndex
        # Return the Document created.
        #
        # See `index_document`.
-       fun index_string(title, uri, string: String, auto_update: nullable Bool): Document do
+       fun index_string(title, uri, string: String, auto_update: nullable Bool): DOC do
                var vector = parse_string(string)
                var doc = new Document(title, uri, vector)
                index_document(doc, auto_update)
@@ -206,7 +231,7 @@ class StringIndex
        # Match the `query` string against all indexed documents
        #
        # See `match_vector`.
-       fun match_string(query: String): Array[IndexMatch] do
+       fun match_string(query: String): Array[IndexMatch[DOC]] do
                var vector = parse_string(query)
                var doc = new Document("", "", vector)
                return match_vector(doc.terms_frequency)
@@ -221,12 +246,7 @@ class StringIndex
                loop
                        var token = reader.read_word
                        if token == "" then break
-
-                       if not vector.has_key(token) then
-                               vector[token] = 1.0
-                       else
-                               vector[token] += 1.0
-                       end
+                       vector.inc(token)
                end
                return vector
        end
@@ -241,7 +261,7 @@ class FileIndex
        # Return the created document or null if `path` is not accepted by `accept_file`.
        #
        # See `index_document`.
-       fun index_file(path: String, auto_update: nullable Bool): nullable Document do
+       fun index_file(path: String, auto_update: nullable Bool): nullable DOC do
                if not accept_file(path) then return null
                var vector = parse_file(path)
                var doc = new Document(path, path, vector)
@@ -347,17 +367,17 @@ class Document
        # A high weight in tf–idf is reached by a high term frequency
        # (in the given document) and a low document frequency of the term in the
        # whole collection of documents
-       var tfidf = new Vector
+       var tfidf: Vector = terms_count is lazy
 
        redef fun to_s do return "{title}"
 end
 
 # A match to a `request` in an `Index`
-class IndexMatch
+class IndexMatch[DOC: Document]
        super Comparable
 
        # Document matching the `request_vector`
-       var document: Document
+       var document: DOC
 
        # Similarity between the `request` and the `doc`.
        #
@@ -372,7 +392,7 @@ end
 class IndexMatchSorter
        super DefaultComparator
 
-       redef type COMPARED: IndexMatch
+       redef type COMPARED: IndexMatch[Document]
 
        redef fun compare(a, b) do
                return b.similarity <=> a.similarity
index c5ea6bb..f1a559a 100644 (file)
@@ -148,14 +148,14 @@ class WebsocketConnection
                var ans_buffer = new Bytes.with_capacity(msg.byte_length + 2)
                # Flag for final frame set to 1
                # opcode set to 1 (for text)
-               ans_buffer.add(129u8)
+               ans_buffer.add(129)
                if msg.length < 126 then
-                       ans_buffer.add(msg.length.to_b)
+                       ans_buffer.add(msg.length)
                end
                if msg.length >= 126 and msg.length <= 65535 then
-                       ans_buffer.add(126u8)
-                       ans_buffer.add((msg.length >> 8).to_b)
-                       ans_buffer.add(msg.length.to_b)
+                       ans_buffer.add(126)
+                       ans_buffer.add(msg.length >> 8)
+                       ans_buffer.add(msg.length)
                end
                msg.append_to_bytes(ans_buffer)
                return ans_buffer
diff --git a/misc/Nit_Compiler.lttng b/misc/Nit_Compiler.lttng
new file mode 100644 (file)
index 0000000..b21d50a
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sessions>
+       <session>
+               <name>Nit_Compiler</name>
+               <domains>
+                       <domain>
+                               <type>UST</type>
+                               <buffer_type>PER_UID</buffer_type>
+                               <channels>
+                                       <channel>
+                                               <name>blocking-channel</name>
+                                               <enabled>true</enabled>
+                                               <overwrite_mode>DISCARD</overwrite_mode>
+                                               <subbuffer_size>524288</subbuffer_size>
+                                               <subbuffer_count>4</subbuffer_count>
+                                               <switch_timer_interval>0</switch_timer_interval>
+                                               <read_timer_interval>0</read_timer_interval>
+                                               <output_type>MMAP</output_type>
+                                               <blocking_timeout>0</blocking_timeout>
+                                               <monitor_timer_interval>1000000</monitor_timer_interval>
+                                               <tracefile_size>0</tracefile_size>
+                                               <tracefile_count>0</tracefile_count>
+                                               <live_timer_interval>0</live_timer_interval>
+                                               <events>
+                                                       <event>
+                                                               <name>Nit_Compiler:Object_Instance</name>
+                                                               <enabled>true</enabled>
+                                                               <type>TRACEPOINT</type>
+                                                               <loglevel_type>ALL</loglevel_type>
+                                                       </event>
+                                                       <event>
+                                                               <name>Nit_Compiler:Object_Destroy</name>
+                                                               <enabled>true</enabled>
+                                                               <type>TRACEPOINT</type>
+                                                               <loglevel_type>ALL</loglevel_type>
+                                                       </event>
+                                               </events>
+                                               <contexts/>
+                                       </channel>
+                               </channels>
+                               <trackers/>
+                       </domain>
+                       <domain>
+                               <type>JUL</type>
+                               <buffer_type>PER_UID</buffer_type>
+                               <channels/>
+                       </domain>
+                       <domain>
+                               <type>LOG4J</type>
+                               <buffer_type>PER_UID</buffer_type>
+                               <channels/>
+                       </domain>
+                       <domain>
+                               <type>PYTHON</type>
+                               <buffer_type>PER_UID</buffer_type>
+                               <channels/>
+                       </domain>
+               </domains>
+               <started>false</started>
+               <output>
+                       <consumer_output>
+                               <enabled>true</enabled>
+                               <destination>
+                                       <path>Put your path here !</path>
+                               </destination>
+                       </consumer_output>
+               </output>
+       </session>
+</sessions>
index d29a131..eff6232 100644 (file)
@@ -249,7 +249,25 @@ For more debugging-related options, see also `--hardening` and `NIT_GC_OPTION`
 ### `--trace`
 Compile with lttng's instrumentation.
 
-Currently add a lttng trace provider and add tracepoint into object instances.
+Currently add a lttng trace provider and add tracepoint into object instances and destructions.
+
+The lttng nit/misc/Nit_Compiler.lttng file is a template that you can use instead of configure channels by yourself. You have to configure the path of the destination tracefile. <destination> <path> "your path" </path> </destination>
+
+To create a channel with template :
+       lttng-sessiond --daemonize
+       lttng load -i=~/nit/misc/Nit_Compiler.lttng Nit_Compiler
+To create a channel without template :
+       lttng create session_name
+       lttng enable-event --userspace Nit_Compiler:Object_Instance
+       lttng enable-event --userspace Nit_Compiler:Object_Destroy
+To record some traces :
+       lttng start
+       --> run your program
+       lttng stop
+To read some traces :
+       babeltrace ~/session_name
+To destroy your current tracing session :
+       lttng destroy
 
 ## COMPILATION MODES
 
index 122ce85..4a4da91 100644 (file)
@@ -66,6 +66,9 @@ Check manpages files.
 ### `--gen-man`
 Generate manpages files.
 
+### `--check-readme`
+Check README.md files.
+
 ### `-f`, `--force`
 Force update of existing files.
 
diff --git a/share/nitdoc/css/Nitdoc.GitHub.css b/share/nitdoc/css/Nitdoc.GitHub.css
deleted file mode 100644 (file)
index a2d675f..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/* \r
- * Nitdoc Github Login Box\r
- */\r
-\r
-#nitdoc-github-li.current {\r
-       color: #999;\r
-}\r
-\r
-#nitdoc-github-li .glyphicon {\r
-       cursor: pointer;\r
-}\r
-\r
-#nitdoc-github-loginbox {\r
-       cursor: default;\r
-       position: absolute;\r
-       width : 220px;\r
-       margin-top: 2px;\r
-       margin-left: -10px;\r
-       display: block;\r
-       padding: 10px;\r
-       text-align: left;\r
-       white-space: normal;\r
-       background-color: #ffffff;\r
-       border: 1px solid #ccc;\r
-       border: 1px solid rgba(0, 0, 0, 0.2);\r
-       -webkit-border-radius: 2px;\r
-       -moz-border-radius: 2px;\r
-       border-radius: 2px;\r
-       -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-       -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-       box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-       -webkit-background-clip: padding-box;\r
-       -moz-background-clip: padding;\r
-       background-clip: padding-box;\r
-}\r
-\r
-#nitdoc-github-loginbox .nitdoc-github-loginbox-arrow {\r
-       position: absolute;\r
-       display: block;\r
-       width: 0;\r
-       height: 0;\r
-       border-color: transparent;\r
-       border-style: solid;\r
-       border-width: 7px;\r
-       top: -7px;\r
-       margin-left: 2px;\r
-       border-bottom-color: #999;\r
-       border-bottom-color: rgba(0, 0, 0, 0.25);\r
-       border-top-width: 0;\r
-}\r
-\r
-#nitdoc-github-loginbox .nitdoc-github-loginbox-arrow:after {\r
-       position: absolute;\r
-       display: block;\r
-       width: 0;\r
-       height: 0;\r
-       border-color: transparent;\r
-       border-style: solid;\r
-       border-width: 10px;\r
-       content: "";\r
-       top: 1px;\r
-       margin-left: -10px;\r
-       border-bottom-color: #ffffff;\r
-       border-top-width: 0;\r
-}\r
-\r
-#nitdoc-github-loginbox h3 {\r
-       text-align:center;\r
-}\r
-\r
-#nitdoc-github-loginbox h4 {\r
-       display: block;\r
-       width: 100%;\r
-       color: #6C6C6C;\r
-       font-style: normal;\r
-       text-align: center;\r
-       margin-bottom: 20px;\r
-}\r
-\r
-\r
-#nitdoc-github-loginbox a.nitdoc-github-loginbox-githublink {\r
-       display: block;\r
-       margin: 10px;\r
-       color: #0D8921;\r
-}\r
-\r
-/* Comment editing */\r
-\r
-.nitdoc-github-commentbox {\r
-       margin: 1em 5px;\r
-       border: 1px solid #eee;\r
-       padding: 1em;\r
-       background: #fff;\r
-       -moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
-       -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
-       box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
-}\r
-\r
-.nitdoc-github-commentbox h3 {\r
-       margin: 0;\r
-}\r
-\r
-.nitdoc-github-commentbox-buttons {\r
-       text-align: right;\r
-}\r
-\r
-.nitdoc-github-commentbox dl {\r
-       margin-bottom: 0;\r
-}\r
-\r
-.nitdoc-github-commentbox dt {\r
-       margin-bottom: 0.5em;\r
-}\r
-\r
-.nitdoc-github-commentbox dd {\r
-       margin: 0 0 1em 0;\r
-}\r
-\r
-.nitdoc-github-commentbox textarea {\r
-       display: block;\r
-       font-family: monospace;\r
-       font-size: 1em;\r
-       width: 100%;\r
-       padding: 4px;\r
-       padding-left: 11px;\r
-       overflow-y: hidden;\r
-       border: 1px solid #CCC;\r
-}\r
-\r
-.nitdoc-github-preview {\r
-       margin: 0 15px;\r
-       cursor: pointer;\r
-}\r
-\r
-.nitdoc-github-button.nitdoc-github-cancel {\r
-       background-color: #b33630;\r
-       background-image: -webkit-gradient(linear, left top, left bottom, from(#E97A74), to(#9f312c)); /* Saf4+, Chrome */\r
-       background-image: -webkit-linear-gradient(top, #E97A74, #9f312c); /* Chrome 10+, Saf5.1+ */\r
-       background-image:    -moz-linear-gradient(top, #E97A74, #9f312c); /* FF3.6 */\r
-       background-image:     -ms-linear-gradient(top, #E97A74, #9f312c); /* IE10 */\r
-       background-image:      -o-linear-gradient(top, #E97A74, #9f312c); /* Opera 11.10+ */\r
-       background-image:         linear-gradient(top, #E97A74, #9f312c);\r
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#E97A74', EndColorStr='#9f312c'); /* IE6–IE9 */\r
-       border: 1px solid #9f312c;\r
-}\r
-\r
-div.comment.locked {\r
-       color: gray;\r
-}\r
-p.locked {\r
-       color: black;\r
-}\r
-\r
-a.nitdoc-github-cancel {\r
-       color: #b33630;\r
-       cursor: pointer;\r
-}\r
-\r
-a.nitdoc-github-update {\r
-       color: orange;\r
-       cursor: pointer;\r
-}\r
-\r
-.nitdoc-dialog h4 {\r
-       font-weight: bold;\r
-}\r
-\r
-/* hljs */\r
-\r
-.hljs.nitcode {\r
-       padding-left: 10px;\r
-}\r
-\r
-.hljs-comment, .hljs-comment-block {\r
-       color: #777;\r
-}\r
-\r
-.hljs-keyword {\r
-       color: #000;\r
-       font-weight: bold;\r
-}\r
-\r
-.hljs-title {\r
-       font-weight: bold;\r
-}\r
-\r
-.hljs-module {\r
-       color: #3762E4;\r
-}\r
-\r
-.hljs-class .hljs-title {\r
-       color: #3762E4;\r
-}\r
-\r
-.hljs-type {\r
-       color: #3762E4;\r
-}\r
-\r
-.hljs-string {\r
-       color: #8F1546;\r
-}\r
-\r
-.hljs-subst {\r
-       color: #9E6BEB;\r
-}\r
-\r
-.hljs-fun .hljs-title {\r
-       color: #3762E4;\r
-}\r
-\r
-.hljs-char, .hljs-number {\r
-       color: #009999;\r
-}\r
diff --git a/share/nitdoc/css/Nitdoc.ModalBox.css b/share/nitdoc/css/Nitdoc.ModalBox.css
deleted file mode 100644 (file)
index bf9f9aa..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/* \r
- * Nitdoc ModalBox style\r
- */\r
-\r
-.nitdoc-dialog-fade {\r
-       background: #000;\r
-       position: fixed; left: 0; top: 0;\r
-       width: 100%; height: 100%;\r
-       opacity: .80;\r
-       filter: alpha(opacity=80);\r
-       z-index: 9999;\r
-}\r
-\r
-.nitdoc-dialog {\r
-       background: #fff;\r
-       border: 1px solid #ddd;\r
-       float: left;\r
-       position: fixed;\r
-       z-index: 99999;\r
-       -webkit-box-shadow: 0px 0px 20px #000;\r
-       -moz-box-shadow: 0px 0px 20px #000;\r
-       box-shadow: 0px 0px 20px #000;\r
-       -webkit-border-radius: 2px;\r
-       -moz-border-radius: 2px;\r
-       border-radius: 2px;\r
-       text-align: left;\r
-       min-width: 300px;\r
-}\r
-\r
-.nitdoc-dialog-header {\r
-       padding: 10px 10px 10px 20px;\r
-       background: #f1f1f1;\r
-       border-bottom: 1px solid #ddd;\r
-}\r
-\r
-.nitdoc-dialog-error .nitdoc-dialog-header {\r
-       background: #C92020;\r
-}\r
-.nitdoc-dialog-error .nitdoc-dialog-header h3 {\r
-       color: white;\r
-}\r
-\r
-.nitdoc-dialog h3 {\r
-       display: inline;\r
-       margin: 0;\r
-}\r
-\r
-.nitdoc-dialog-content {\r
-       max-height: 450px;\r
-       overflow-y: scroll;\r
-       padding: 10px;\r
-}\r
-\r
-.nitdoc-dialog-buttons {\r
-       text-align: right;\r
-       padding: 5px;\r
-       border-top: 1px solid #ddd;\r
-}\r
-\r
-.nitdoc-dialog textarea {\r
-       min-width: 300px;\r
-       width: 100%;\r
-}\r
-\r
-.nitdoc-dialog button {\r
-       cursor: pointer;\r
-       border-radius: 2px;\r
-       -moz-border-radius: 2px;\r
-       -webkit-border-radius: 2px;\r
-       font-size: 14px;\r
-       padding: 5px 7px 5px 7px;\r
-       text-align: center;\r
-       background: #eee;\r
-       color: #333;\r
-       border: 1px solid #ddd;\r
-       font-weight: bold;\r
-}\r
-\r
-.nitdoc-dialog button:hover {\r
-       background: #0D8921;\r
-       color: #fff;\r
-       border: 1px solid #1d7900;\r
-}\r
-\r
-.nitdoc-dialog-close {\r
-       float: right;\r
-       padding: 5px;\r
-       margin: 0px;\r
-       line-height: 10px;\r
-       text-transform: lowercase;\r
-}\r
-\r
diff --git a/share/nitdoc/css/Nitdoc.QuickSearch.css b/share/nitdoc/css/Nitdoc.QuickSearch.css
deleted file mode 100644 (file)
index 81bba5d..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/* \r
- * Nitdoc Quick Search JS module \r
- */\r
-\r
-#nitdoc-qs-field {\r
-       width: 300px;\r
-       margin-top: 3px;\r
-}\r
-\r
-#nitdoc-qs-table {\r
-       background-color: #FFFFFF;\r
-       border: 1px solid #E0E0E0;\r
-       border-spacing: 0px;\r
-       z-index: 1000;\r
-       -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-       -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-       box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\r
-}\r
-\r
-#nitdoc-qs-table .nitdoc-qs-active {\r
-       cursor: pointer;\r
-       background: #EEE;\r
-}\r
-\r
-#nitdoc-qs-table td, th {\r
-       white-space: nowrap;\r
-       overflow: hidden;\r
-       line-height: 22px;\r
-       padding: 2px;\r
-}\r
-\r
-#nitdoc-qs-table td.nitdoc-qs-sub {\r
-       color: #6C6C6C;\r
-       padding-left: 12px;\r
-}\r
-\r
-#nitdoc-qs-table td.nitdoc-qs-info {\r
-       color: #0D8921;\r
-       font-size: smaller;\r
-       text-align: right;\r
-}\r
-\r
-#nitdoc-qs-table tr.nitdoc-qs-noresult td {\r
-       color: #6C6C6C;\r
-       font-size: small;\r
-       line-height: 15px;\r
-}\r
-\r
-#nitdoc-qs-table tr.nitdoc-qs-overflow td {\r
-       text-align: center;\r
-       font-size:      x-small;\r
-       line-height: 10px;\r
-       color: #FFF;\r
-       -webkit-touch-callout: none;\r
-       -webkit-user-select: none;\r
-       -khtml-user-select: none;\r
-       -moz-user-select: none;\r
-       -ms-user-select: none;\r
-       user-select: none;\r
-}\r
-\r
-#nitdoc-qs-table tr.nitdoc-qs-overflow-active td {\r
-       color: #0D8921;\r
-       cursor: pointer;\r
-}\r
-\r
-#nitdoc-qs-table tr.nitdoc-qs-overflow-active td:hover {\r
-       background-color: #E0E0E0;\r
-}\r
diff --git a/share/nitdoc/css/Nitdoc.UI.css b/share/nitdoc/css/Nitdoc.UI.css
deleted file mode 100644 (file)
index 17b248d..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/* \r
- * Nitdoc UI JS module \r
- */\r
-\r
-\r
-/* Folding */\r
-\r
-a.nitdoc-ui-fold {\r
-       margin: 0 5px;\r
-       color: #999;\r
-       font-family: monospace;\r
-       font-weight: bold;\r
-       font-size: 120%;\r
-}\r
-\r
-/* Search page field */\r
-\r
-.nitdoc-ui-searchpage-field {\r
-       width: 750px;\r
-}\r
-\r
-/* Side bar boxes text filtering */\r
-\r
-.nitdoc-ui-filter {\r
-       text-align: center;\r
-       padding: 5px;\r
-}\r
-\r
-.nitdoc-ui-filter-field {\r
-       width: 150px;\r
-       margin-right: 5px;\r
-}\r
-\r
-.nitdoc-ui-filter-field-notused {\r
-       color: #999;\r
-       font-style: italic;\r
-}\r
-\r
-/* Side bar boxes type filtering */\r
-\r
-a.nitdoc-ui-filter-link {\r
-       color: #0D8921;\r
-       cursor: pointer;\r
-       font-family: monospace;\r
-       margin-right: 5px;\r
-       font-weight: bold;\r
-}\r
-\r
-a.nitdoc-ui-filter-link:hover {\r
-       text-decoration: underline;\r
-}\r
-\r
-a.nitdoc-ui-filter-hidden {\r
-       color: #999;\r
-       font-weight: normal;\r
-}\r
-\r
index 0351b6f..fd80998 100644 (file)
@@ -1,13 +1,3 @@
-/*!
- * Bootstrap v3.1.1
- *
- * Copyright 2014 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world by @mdo and @fat.
- * BootSwatchr built and provided by @DrewStrickland
- */
 /*! normalize.css v3.0.0 | MIT License | git.io/normalize */
 html {
   font-family: sans-serif;
@@ -275,11 +265,11 @@ html {
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 }
 body {
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: sans-serif;
   font-size: 14px;
   line-height: 1.428571429;
   color: #333333;
-  background-color: #ffffff;
+  background-color: #f2f2f2;
 }
 input,
 button,
@@ -290,12 +280,12 @@ textarea {
   line-height: inherit;
 }
 a {
-  color: #222222;
+  color: #0d8921;
   text-decoration: none;
 }
 a:hover,
 a:focus {
-  color: #0d8921;
+  color: #064310;
   text-decoration: underline;
 }
 a:focus {
@@ -319,14 +309,14 @@ img {
   height: auto;
 }
 .img-rounded {
-  border-radius: 4px;
+  border-radius: 0px;
 }
 .img-thumbnail {
   padding: 4px;
   line-height: 1.428571429;
-  background-color: #ffffff;
+  background-color: #f2f2f2;
   border: 1px solid #dddddd;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-transition: all 0.2s ease-in-out;
   transition: all 0.2s ease-in-out;
   display: inline-block;
@@ -340,7 +330,7 @@ hr {
   margin-top: 20px;
   margin-bottom: 20px;
   border: 0;
-  border-top: 1px solid #eeeeee;
+  border-top: 1px solid #ddd;
 }
 .sr-only {
   position: absolute;
@@ -364,7 +354,7 @@ h6,
 .h4,
 .h5,
 .h6 {
-  font-family: inherit;
+  font-family: sans-serif;
   font-weight: 500;
   line-height: 1.1;
   color: inherit;
@@ -453,11 +443,11 @@ h2,
 }
 h3,
 .h3 {
-  font-size: 24px;
+  font-size: 23px;
 }
 h4,
 .h4 {
-  font-size: 18px;
+  font-size: 17px;
 }
 h5,
 .h5 {
@@ -465,7 +455,7 @@ h5,
 }
 h6,
 .h6 {
-  font-size: 12px;
+  font-size: 11px;
 }
 p {
   margin: 0 0 10px;
@@ -516,10 +506,10 @@ a.text-success:hover {
   color: #449d44;
 }
 .text-info {
-  color: #6c6c6c;
+  color: #5bc0de;
 }
 a.text-info:hover {
-  color: #525252;
+  color: #31b0d5;
 }
 .text-warning {
   color: #f0ad4e;
@@ -541,28 +531,28 @@ a.bg-primary:hover {
   background-color: #095a16;
 }
 .bg-success {
-  background-color: #eaf6ea;
+  background-color: #dff0d8;
 }
 a.bg-success:hover {
-  background-color: #c7e6c7;
+  background-color: #c1e2b3;
 }
 .bg-info {
-  background-color: #ececec;
+  background-color: #d9edf7;
 }
 a.bg-info:hover {
-  background-color: #d2d2d2;
+  background-color: #afd9ee;
 }
 .bg-warning {
-  background-color: #fef9f3;
+  background-color: #fcf8e3;
 }
 a.bg-warning:hover {
-  background-color: #fae3c4;
+  background-color: #f7ecb5;
 }
 .bg-danger {
-  background-color: #f9e2e2;
+  background-color: #f2dede;
 }
 a.bg-danger:hover {
-  background-color: #f0b9b8;
+  background-color: #e4b9b9;
 }
 .page-header {
   padding-bottom: 9px;
@@ -587,13 +577,15 @@ ol ol {
 .list-inline {
   padding-left: 0;
   list-style: none;
-  margin-left: -5px;
 }
 .list-inline > li {
   display: inline-block;
   padding-left: 5px;
   padding-right: 5px;
 }
+.list-inline > li:first-child {
+  padding-left: 0;
+}
 dl {
   margin-top: 0;
   margin-bottom: 20px;
@@ -692,7 +684,7 @@ code,
 kbd,
 pre,
 samp {
-  font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+  font-family: monospace;
 }
 code {
   padding: 2px 4px;
@@ -700,14 +692,14 @@ code {
   color: #c7254e;
   background-color: #f9f2f4;
   white-space: nowrap;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 kbd {
   padding: 2px 4px;
   font-size: 90%;
   color: #ffffff;
   background-color: #333333;
-  border-radius: 2px;
+  border-radius: 0px;
   box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
 }
 pre {
@@ -721,7 +713,7 @@ pre {
   color: #333333;
   background-color: #f5f5f5;
   border: 1px solid #cccccc;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 pre code {
   padding: 0;
@@ -1440,7 +1432,7 @@ th {
   border-top: 2px solid #dddddd;
 }
 .table .table {
-  background-color: #ffffff;
+  background-color: #f2f2f2;
 }
 .table-condensed > thead > tr > th,
 .table-condensed > tbody > tr > th,
@@ -1471,7 +1463,7 @@ th {
 }
 .table-hover > tbody > tr:hover > td,
 .table-hover > tbody > tr:hover > th {
-  background-color: #f5f5f5;
+  background-color: #dbdbdb;
 }
 table col[class*="col-"] {
   position: static;
@@ -1496,13 +1488,13 @@ table th[class*="col-"] {
 .table > thead > tr.active > th,
 .table > tbody > tr.active > th,
 .table > tfoot > tr.active > th {
-  background-color: #f5f5f5;
+  background-color: #dbdbdb;
 }
 .table-hover > tbody > tr > td.active:hover,
 .table-hover > tbody > tr > th.active:hover,
 .table-hover > tbody > tr.active:hover > td,
 .table-hover > tbody > tr.active:hover > th {
-  background-color: #e8e8e8;
+  background-color: #cecece;
 }
 .table > thead > tr > td.success,
 .table > tbody > tr > td.success,
@@ -1516,13 +1508,13 @@ table th[class*="col-"] {
 .table > thead > tr.success > th,
 .table > tbody > tr.success > th,
 .table > tfoot > tr.success > th {
-  background-color: #eaf6ea;
+  background-color: #dff0d8;
 }
 .table-hover > tbody > tr > td.success:hover,
 .table-hover > tbody > tr > th.success:hover,
 .table-hover > tbody > tr.success:hover > td,
 .table-hover > tbody > tr.success:hover > th {
-  background-color: #d8eed8;
+  background-color: #d0e9c6;
 }
 .table > thead > tr > td.info,
 .table > tbody > tr > td.info,
@@ -1536,13 +1528,13 @@ table th[class*="col-"] {
 .table > thead > tr.info > th,
 .table > tbody > tr.info > th,
 .table > tfoot > tr.info > th {
-  background-color: #ececec;
+  background-color: #d9edf7;
 }
 .table-hover > tbody > tr > td.info:hover,
 .table-hover > tbody > tr > th.info:hover,
 .table-hover > tbody > tr.info:hover > td,
 .table-hover > tbody > tr.info:hover > th {
-  background-color: #dfdfdf;
+  background-color: #c4e3f3;
 }
 .table > thead > tr > td.warning,
 .table > tbody > tr > td.warning,
@@ -1556,13 +1548,13 @@ table th[class*="col-"] {
 .table > thead > tr.warning > th,
 .table > tbody > tr.warning > th,
 .table > tfoot > tr.warning > th {
-  background-color: #fef9f3;
+  background-color: #fcf8e3;
 }
 .table-hover > tbody > tr > td.warning:hover,
 .table-hover > tbody > tr > th.warning:hover,
 .table-hover > tbody > tr.warning:hover > td,
 .table-hover > tbody > tr.warning:hover > th {
-  background-color: #fceedb;
+  background-color: #faf2cc;
 }
 .table > thead > tr > td.danger,
 .table > tbody > tr > td.danger,
@@ -1576,13 +1568,13 @@ table th[class*="col-"] {
 .table > thead > tr.danger > th,
 .table > tbody > tr.danger > th,
 .table > tfoot > tr.danger > th {
-  background-color: #f9e2e2;
+  background-color: #f2dede;
 }
 .table-hover > tbody > tr > td.danger:hover,
 .table-hover > tbody > tr > th.danger:hover,
 .table-hover > tbody > tr.danger:hover > td,
 .table-hover > tbody > tr.danger:hover > th {
-  background-color: #f4cecd;
+  background-color: #ebcccc;
 }
 @media (max-width: 767px) {
   .table-responsive {
@@ -1663,6 +1655,7 @@ input[type="checkbox"] {
   margin: 4px 0 0;
   margin-top: 1px \9;
   /* IE8-9 */
+
   line-height: normal;
 }
 input[type="file"] {
@@ -1685,7 +1678,7 @@ input[type="checkbox"]:focus {
 }
 output {
   display: block;
-  padding-top: 3px;
+  padding-top: 7px;
   font-size: 14px;
   line-height: 1.428571429;
   color: #555555;
@@ -1693,25 +1686,25 @@ output {
 .form-control {
   display: block;
   width: 100%;
-  height: 26px;
-  padding: 2px 5px;
+  height: 34px;
+  padding: 6px 12px;
   font-size: 14px;
   line-height: 1.428571429;
   color: #555555;
   background-color: #ffffff;
   background-image: none;
   border: 1px solid #cccccc;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
   box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
   -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
   transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
 }
 .form-control:focus {
-  border-color: #6c6c6c;
+  border-color: #66afe9;
   outline: 0;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(108, 108, 108, 0.6);
-  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(108, 108, 108, 0.6);
+  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 }
 .form-control::-moz-placeholder {
   color: #999999;
@@ -1737,7 +1730,7 @@ input[type="search"] {
   -webkit-appearance: none;
 }
 input[type="date"] {
-  line-height: 26px;
+  line-height: 34px;
 }
 .form-group {
   margin-bottom: 15px;
@@ -1796,30 +1789,30 @@ fieldset[disabled] .checkbox-inline {
   cursor: not-allowed;
 }
 .input-sm {
-  height: 22px;
-  padding: 1px 5px;
+  height: 30px;
+  padding: 5px 10px;
   font-size: 12px;
   line-height: 1.5;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 select.input-sm {
-  height: 22px;
-  line-height: 22px;
+  height: 30px;
+  line-height: 30px;
 }
 textarea.input-sm,
 select[multiple].input-sm {
   height: auto;
 }
 .input-lg {
-  height: 36px;
-  padding: 5px 10px;
+  height: 45px;
+  padding: 10px 16px;
   font-size: 18px;
   line-height: 1.33;
-  border-radius: 4px;
+  border-radius: 0px;
 }
 select.input-lg {
-  height: 36px;
-  line-height: 36px;
+  height: 45px;
+  line-height: 45px;
 }
 textarea.input-lg,
 select[multiple].input-lg {
@@ -1829,16 +1822,16 @@ select[multiple].input-lg {
   position: relative;
 }
 .has-feedback .form-control {
-  padding-right: 32.5px;
+  padding-right: 42.5px;
 }
 .has-feedback .form-control-feedback {
   position: absolute;
   top: 25px;
   right: 0;
   display: block;
-  width: 26px;
-  height: 26px;
-  line-height: 26px;
+  width: 34px;
+  height: 34px;
+  line-height: 34px;
   text-align: center;
 }
 .has-success .help-block,
@@ -1862,7 +1855,7 @@ select[multiple].input-lg {
 .has-success .input-group-addon {
   color: #5cb85c;
   border-color: #5cb85c;
-  background-color: #eaf6ea;
+  background-color: #dff0d8;
 }
 .has-success .form-control-feedback {
   color: #5cb85c;
@@ -1888,7 +1881,7 @@ select[multiple].input-lg {
 .has-warning .input-group-addon {
   color: #f0ad4e;
   border-color: #f0ad4e;
-  background-color: #fef9f3;
+  background-color: #fcf8e3;
 }
 .has-warning .form-control-feedback {
   color: #f0ad4e;
@@ -1914,7 +1907,7 @@ select[multiple].input-lg {
 .has-error .input-group-addon {
   color: #d9534f;
   border-color: #d9534f;
-  background-color: #f9e2e2;
+  background-color: #f2dede;
 }
 .has-error .form-control-feedback {
   color: #d9534f;
@@ -1970,18 +1963,18 @@ select[multiple].input-lg {
 .form-horizontal .checkbox-inline {
   margin-top: 0;
   margin-bottom: 0;
-  padding-top: 3px;
+  padding-top: 7px;
 }
 .form-horizontal .radio,
 .form-horizontal .checkbox {
-  min-height: 23px;
+  min-height: 27px;
 }
 .form-horizontal .form-group {
   margin-left: -15px;
   margin-right: -15px;
 }
 .form-horizontal .form-control-static {
-  padding-top: 3px;
+  padding-top: 7px;
 }
 @media (min-width: 768px) {
   .form-horizontal .control-label {
@@ -2002,18 +1995,17 @@ select[multiple].input-lg {
   background-image: none;
   border: 1px solid transparent;
   white-space: nowrap;
-  padding: 2px 5px;
+  padding: 6px 12px;
   font-size: 14px;
   line-height: 1.428571429;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
+  -o-user-select: none;
   user-select: none;
 }
-.btn:focus,
-.btn:active:focus,
-.btn.active:focus {
+.btn:focus {
   outline: thin dotted;
   outline: 5px auto -webkit-focus-ring-color;
   outline-offset: -2px;
@@ -2165,8 +2157,8 @@ fieldset[disabled] .btn-success.active {
 }
 .btn-info {
   color: #ffffff;
-  background-color: #6c6c6c;
-  border-color: #5f5f5f;
+  background-color: #5bc0de;
+  border-color: #46b8da;
 }
 .btn-info:hover,
 .btn-info:focus,
@@ -2174,8 +2166,8 @@ fieldset[disabled] .btn-success.active {
 .btn-info.active,
 .open .dropdown-toggle.btn-info {
   color: #ffffff;
-  background-color: #585858;
-  border-color: #414141;
+  background-color: #39b3d7;
+  border-color: #269abc;
 }
 .btn-info:active,
 .btn-info.active,
@@ -2197,11 +2189,11 @@ fieldset[disabled] .btn-info:active,
 .btn-info.disabled.active,
 .btn-info[disabled].active,
 fieldset[disabled] .btn-info.active {
-  background-color: #6c6c6c;
-  border-color: #5f5f5f;
+  background-color: #5bc0de;
+  border-color: #46b8da;
 }
 .btn-info .badge {
-  color: #6c6c6c;
+  color: #5bc0de;
   background-color: #ffffff;
 }
 .btn-warning {
@@ -2287,7 +2279,7 @@ fieldset[disabled] .btn-danger.active {
   background-color: #ffffff;
 }
 .btn-link {
-  color: #222222;
+  color: #0d8921;
   font-weight: normal;
   cursor: pointer;
   border-radius: 0;
@@ -2308,7 +2300,7 @@ fieldset[disabled] .btn-link {
 }
 .btn-link:hover,
 .btn-link:focus {
-  color: #0d8921;
+  color: #064310;
   text-decoration: underline;
   background-color: transparent;
 }
@@ -2321,24 +2313,24 @@ fieldset[disabled] .btn-link:focus {
 }
 .btn-lg,
 .btn-group-lg > .btn {
-  padding: 5px 10px;
+  padding: 10px 16px;
   font-size: 18px;
   line-height: 1.33;
-  border-radius: 4px;
+  border-radius: 0px;
 }
 .btn-sm,
 .btn-group-sm > .btn {
-  padding: 1px 5px;
+  padding: 5px 10px;
   font-size: 12px;
   line-height: 1.5;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 .btn-xs,
 .btn-group-xs > .btn {
-  padding: 0px 3px;
+  padding: 1px 5px;
   font-size: 12px;
   line-height: 1.5;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 .btn-block {
   display: block;
@@ -2377,8 +2369,8 @@ input[type="button"].btn-block {
 }
 @font-face {
   font-family: 'Glyphicons Halflings';
-  src: url('../fonts/glyphicons-halflings-regular.eot');
-  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+  src: url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.eot');
+  src: url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.woff') format('woff'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
 }
 .glyphicon {
   position: relative;
@@ -3022,7 +3014,7 @@ input[type="button"].btn-block {
   background-color: #ffffff;
   border: 1px solid #cccccc;
   border: 1px solid rgba(0, 0, 0, 0.15);
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
   box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
   background-clip: padding-box;
@@ -3049,8 +3041,8 @@ input[type="button"].btn-block {
 .dropdown-menu > li > a:hover,
 .dropdown-menu > li > a:focus {
   text-decoration: none;
-  color: #262626;
-  background-color: #f5f5f5;
+  color: #ffffff;
+  background-color: #0d8921;
 }
 .dropdown-menu > .active > a,
 .dropdown-menu > .active > a:hover,
@@ -3253,12 +3245,12 @@ input[type="button"].btn-block {
   border-radius: 0;
 }
 .btn-group-vertical > .btn:first-child:not(:last-child) {
-  border-top-right-radius: 3px;
+  border-top-right-radius: 0px;
   border-bottom-right-radius: 0;
   border-bottom-left-radius: 0;
 }
 .btn-group-vertical > .btn:last-child:not(:first-child) {
-  border-bottom-left-radius: 3px;
+  border-bottom-left-radius: 0px;
   border-top-right-radius: 0;
   border-top-left-radius: 0;
 }
@@ -3304,8 +3296,6 @@ input[type="button"].btn-block {
   padding-right: 0;
 }
 .input-group .form-control {
-  position: relative;
-  z-index: 2;
   float: left;
   width: 100%;
   margin-bottom: 0;
@@ -3313,17 +3303,17 @@ input[type="button"].btn-block {
 .input-group-lg > .form-control,
 .input-group-lg > .input-group-addon,
 .input-group-lg > .input-group-btn > .btn {
-  height: 36px;
-  padding: 5px 10px;
+  height: 45px;
+  padding: 10px 16px;
   font-size: 18px;
   line-height: 1.33;
-  border-radius: 4px;
+  border-radius: 0px;
 }
 select.input-group-lg > .form-control,
 select.input-group-lg > .input-group-addon,
 select.input-group-lg > .input-group-btn > .btn {
-  height: 36px;
-  line-height: 36px;
+  height: 45px;
+  line-height: 45px;
 }
 textarea.input-group-lg > .form-control,
 textarea.input-group-lg > .input-group-addon,
@@ -3336,17 +3326,17 @@ select[multiple].input-group-lg > .input-group-btn > .btn {
 .input-group-sm > .form-control,
 .input-group-sm > .input-group-addon,
 .input-group-sm > .input-group-btn > .btn {
-  height: 22px;
-  padding: 1px 5px;
+  height: 30px;
+  padding: 5px 10px;
   font-size: 12px;
   line-height: 1.5;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 select.input-group-sm > .form-control,
 select.input-group-sm > .input-group-addon,
 select.input-group-sm > .input-group-btn > .btn {
-  height: 22px;
-  line-height: 22px;
+  height: 30px;
+  line-height: 30px;
 }
 textarea.input-group-sm > .form-control,
 textarea.input-group-sm > .input-group-addon,
@@ -3373,7 +3363,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   vertical-align: middle;
 }
 .input-group-addon {
-  padding: 2px 5px;
+  padding: 6px 12px;
   font-size: 14px;
   font-weight: normal;
   line-height: 1;
@@ -3381,17 +3371,17 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   text-align: center;
   background-color: #eeeeee;
   border: 1px solid #cccccc;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .input-group-addon.input-sm {
-  padding: 1px 5px;
+  padding: 5px 10px;
   font-size: 12px;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 .input-group-addon.input-lg {
-  padding: 5px 10px;
+  padding: 10px 16px;
   font-size: 18px;
-  border-radius: 4px;
+  border-radius: 0px;
 }
 .input-group-addon input[type="radio"],
 .input-group-addon input[type="checkbox"] {
@@ -3459,12 +3449,12 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 .nav > li > a {
   position: relative;
   display: block;
-  padding: 5px 10px;
+  padding: 10px 15px;
 }
 .nav > li > a:hover,
 .nav > li > a:focus {
   text-decoration: none;
-  background-color: #eeeeee;
+  background-color: #dddddd;
 }
 .nav > li.disabled > a {
   color: #999999;
@@ -3479,8 +3469,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 .nav .open > a,
 .nav .open > a:hover,
 .nav .open > a:focus {
-  background-color: #eeeeee;
-  border-color: #222222;
+  background-color: #dddddd;
+  border-color: #0d8921;
 }
 .nav .nav-divider {
   height: 1px;
@@ -3502,7 +3492,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   margin-right: 2px;
   line-height: 1.428571429;
   border: 1px solid transparent;
-  border-radius: 3px 3px 0 0;
+  border-radius: 0px 0px 0 0;
 }
 .nav-tabs > li > a:hover {
   border-color: #eeeeee #eeeeee #dddddd;
@@ -3511,7 +3501,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 .nav-tabs > li.active > a:hover,
 .nav-tabs > li.active > a:focus {
   color: #555555;
-  background-color: #ffffff;
+  background-color: #f2f2f2;
   border: 1px solid #dddddd;
   border-bottom-color: transparent;
   cursor: default;
@@ -3542,7 +3532,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 }
 .nav-tabs.nav-justified > li > a {
   margin-right: 0;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .nav-tabs.nav-justified > .active > a,
 .nav-tabs.nav-justified > .active > a:hover,
@@ -3552,19 +3542,19 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 @media (min-width: 768px) {
   .nav-tabs.nav-justified > li > a {
     border-bottom: 1px solid #dddddd;
-    border-radius: 3px 3px 0 0;
+    border-radius: 0px 0px 0 0;
   }
   .nav-tabs.nav-justified > .active > a,
   .nav-tabs.nav-justified > .active > a:hover,
   .nav-tabs.nav-justified > .active > a:focus {
-    border-bottom-color: #ffffff;
+    border-bottom-color: #f2f2f2;
   }
 }
 .nav-pills > li {
   float: left;
 }
 .nav-pills > li > a {
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .nav-pills > li + li {
   margin-left: 2px;
@@ -3610,7 +3600,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 }
 .nav-tabs-justified > li > a {
   margin-right: 0;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .nav-tabs-justified > .active > a,
 .nav-tabs-justified > .active > a:hover,
@@ -3620,12 +3610,12 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 @media (min-width: 768px) {
   .nav-tabs-justified > li > a {
     border-bottom: 1px solid #dddddd;
-    border-radius: 3px 3px 0 0;
+    border-radius: 0px 0px 0 0;
   }
   .nav-tabs-justified > .active > a,
   .nav-tabs-justified > .active > a:hover,
   .nav-tabs-justified > .active > a:focus {
-    border-bottom-color: #ffffff;
+    border-bottom-color: #f2f2f2;
   }
 }
 .tab-content > .tab-pane {
@@ -3641,13 +3631,13 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 }
 .navbar {
   position: relative;
-  min-height: 30px;
+  min-height: 50px;
   margin-bottom: 20px;
   border: 1px solid transparent;
 }
 @media (min-width: 768px) {
   .navbar {
-    border-radius: 3px;
+    border-radius: 0px;
   }
 }
 @media (min-width: 768px) {
@@ -3738,10 +3728,10 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 }
 .navbar-brand {
   float: left;
-  padding: 5px 15px;
+  padding: 15px 15px;
   font-size: 18px;
   line-height: 20px;
-  height: 30px;
+  height: 50px;
 }
 .navbar-brand:hover,
 .navbar-brand:focus {
@@ -3758,12 +3748,12 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   float: right;
   margin-right: 15px;
   padding: 9px 10px;
-  margin-top: -2px;
-  margin-bottom: -2px;
+  margin-top: 8px;
+  margin-bottom: 8px;
   background-color: transparent;
   background-image: none;
   border: 1px solid transparent;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .navbar-toggle:focus {
   outline: none;
@@ -3783,7 +3773,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   }
 }
 .navbar-nav {
-  margin: 2.5px -15px;
+  margin: 7.5px -15px;
 }
 .navbar-nav > li > a {
   padding-top: 10px;
@@ -3821,8 +3811,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
     float: left;
   }
   .navbar-nav > li > a {
-    padding-top: 5px;
-    padding-bottom: 5px;
+    padding-top: 15px;
+    padding-bottom: 15px;
   }
   .navbar-nav.navbar-right:last-child {
     margin-right: -15px;
@@ -3844,8 +3834,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   border-bottom: 1px solid transparent;
   -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
   box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
-  margin-top: 2px;
-  margin-bottom: 2px;
+  margin-top: 8px;
+  margin-bottom: 8px;
 }
 @media (min-width: 768px) {
   .navbar-form .form-group {
@@ -3912,20 +3902,20 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   border-bottom-left-radius: 0;
 }
 .navbar-btn {
-  margin-top: 2px;
-  margin-bottom: 2px;
+  margin-top: 8px;
+  margin-bottom: 8px;
 }
 .navbar-btn.btn-sm {
-  margin-top: 4px;
-  margin-bottom: 4px;
+  margin-top: 10px;
+  margin-bottom: 10px;
 }
 .navbar-btn.btn-xs {
-  margin-top: 4px;
-  margin-bottom: 4px;
+  margin-top: 14px;
+  margin-bottom: 14px;
 }
 .navbar-text {
-  margin-top: 5px;
-  margin-bottom: 5px;
+  margin-top: 15px;
+  margin-bottom: 15px;
 }
 @media (min-width: 768px) {
   .navbar-text {
@@ -3938,33 +3928,33 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   }
 }
 .navbar-default {
-  background-color: #f1f1f1;
-  border-color: #e0e0e0;
+  background-color: #0d8921;
+  border-color: none;
 }
 .navbar-default .navbar-brand {
-  color: #333333;
+  color: #ffffff;
 }
 .navbar-default .navbar-brand:hover,
 .navbar-default .navbar-brand:focus {
-  color: #1a1a1a;
+  color: #e6e6e6;
   background-color: transparent;
 }
 .navbar-default .navbar-text {
-  color: #333333;
+  color: #ffffff;
 }
 .navbar-default .navbar-nav > li > a {
-  color: #333333;
+  color: #ffffff;
 }
 .navbar-default .navbar-nav > li > a:hover,
 .navbar-default .navbar-nav > li > a:focus {
-  color: #0d8921;
+  color: #dddddd;
   background-color: transparent;
 }
 .navbar-default .navbar-nav > .active > a,
 .navbar-default .navbar-nav > .active > a:hover,
 .navbar-default .navbar-nav > .active > a:focus {
   color: #ffffff;
-  background-color: #0d8921;
+  background-color: #0a6b1a;
 }
 .navbar-default .navbar-nav > .disabled > a,
 .navbar-default .navbar-nav > .disabled > a:hover,
@@ -3980,32 +3970,32 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   background-color: #dddddd;
 }
 .navbar-default .navbar-toggle .icon-bar {
-  background-color: #888888;
+  background-color: #ffffff;
 }
 .navbar-default .navbar-collapse,
 .navbar-default .navbar-form {
-  border-color: #e0e0e0;
+  border-color: none;
 }
 .navbar-default .navbar-nav > .open > a,
 .navbar-default .navbar-nav > .open > a:hover,
 .navbar-default .navbar-nav > .open > a:focus {
-  background-color: #0d8921;
+  background-color: #0a6b1a;
   color: #ffffff;
 }
 @media (max-width: 767px) {
   .navbar-default .navbar-nav .open .dropdown-menu > li > a {
-    color: #333333;
+    color: #ffffff;
   }
   .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
   .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
-    color: #0d8921;
+    color: #dddddd;
     background-color: transparent;
   }
   .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
   .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
   .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
     color: #ffffff;
-    background-color: #0d8921;
+    background-color: #0a6b1a;
   }
   .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
   .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
@@ -4015,10 +4005,10 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   }
 }
 .navbar-default .navbar-link {
-  color: #333333;
+  color: #ffffff;
 }
 .navbar-default .navbar-link:hover {
-  color: #0d8921;
+  color: #dddddd;
 }
 .navbar-inverse {
   background-color: #222222;
@@ -4114,13 +4104,13 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   margin-bottom: 20px;
   list-style: none;
   background-color: #f5f5f5;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .breadcrumb > li {
   display: inline-block;
 }
 .breadcrumb > li + li:before {
-  content: "/\00a0";
+  content: "\00a0";
   padding: 0 5px;
   color: #cccccc;
 }
@@ -4131,7 +4121,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   display: inline-block;
   padding-left: 0;
   margin: 20px 0;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .pagination > li {
   display: inline;
@@ -4140,10 +4130,10 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 .pagination > li > span {
   position: relative;
   float: left;
-  padding: 2px 5px;
+  padding: 6px 12px;
   line-height: 1.428571429;
   text-decoration: none;
-  color: #222222;
+  color: #0d8921;
   background-color: #ffffff;
   border: 1px solid #dddddd;
   margin-left: -1px;
@@ -4151,19 +4141,19 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 .pagination > li:first-child > a,
 .pagination > li:first-child > span {
   margin-left: 0;
-  border-bottom-left-radius: 3px;
-  border-top-left-radius: 3px;
+  border-bottom-left-radius: 0px;
+  border-top-left-radius: 0px;
 }
 .pagination > li:last-child > a,
 .pagination > li:last-child > span {
-  border-bottom-right-radius: 3px;
-  border-top-right-radius: 3px;
+  border-bottom-right-radius: 0px;
+  border-top-right-radius: 0px;
 }
 .pagination > li > a:hover,
 .pagination > li > span:hover,
 .pagination > li > a:focus,
 .pagination > li > span:focus {
-  color: #0d8921;
+  color: #064310;
   background-color: #eeeeee;
   border-color: #dddddd;
 }
@@ -4192,33 +4182,33 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
 }
 .pagination-lg > li > a,
 .pagination-lg > li > span {
-  padding: 5px 10px;
+  padding: 10px 16px;
   font-size: 18px;
 }
 .pagination-lg > li:first-child > a,
 .pagination-lg > li:first-child > span {
-  border-bottom-left-radius: 4px;
-  border-top-left-radius: 4px;
+  border-bottom-left-radius: 0px;
+  border-top-left-radius: 0px;
 }
 .pagination-lg > li:last-child > a,
 .pagination-lg > li:last-child > span {
-  border-bottom-right-radius: 4px;
-  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0px;
+  border-top-right-radius: 0px;
 }
 .pagination-sm > li > a,
 .pagination-sm > li > span {
-  padding: 1px 5px;
+  padding: 5px 10px;
   font-size: 12px;
 }
 .pagination-sm > li:first-child > a,
 .pagination-sm > li:first-child > span {
-  border-bottom-left-radius: 2px;
-  border-top-left-radius: 2px;
+  border-bottom-left-radius: 0px;
+  border-top-left-radius: 0px;
 }
 .pagination-sm > li:last-child > a,
 .pagination-sm > li:last-child > span {
-  border-bottom-right-radius: 2px;
-  border-top-right-radius: 2px;
+  border-bottom-right-radius: 0px;
+  border-top-right-radius: 0px;
 }
 .pager {
   padding-left: 0;
@@ -4305,11 +4295,11 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   background-color: #449d44;
 }
 .label-info {
-  background-color: #6c6c6c;
+  background-color: #5bc0de;
 }
 .label-info[href]:hover,
 .label-info[href]:focus {
-  background-color: #525252;
+  background-color: #31b0d5;
 }
 .label-warning {
   background-color: #f0ad4e;
@@ -4331,7 +4321,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
   padding: 3px 7px;
   font-size: 12px;
   font-weight: bold;
-  color: #ffffff;
+  color: : #fff;
   line-height: 1;
   vertical-align: baseline;
   white-space: nowrap;
@@ -4358,41 +4348,41 @@ a.badge:focus {
 }
 a.list-group-item.active > .badge,
 .nav-pills > .active > a > .badge {
-  color: #222222;
+  color: #0d8921;
   background-color: #ffffff;
 }
 .nav-pills > li > a > .badge {
   margin-left: 3px;
 }
 .jumbotron {
-  padding: 20px;
-  margin-bottom: 20px;
+  padding: 30px;
+  margin-bottom: 30px;
   color: inherit;
-  background-color: #eeeeee;
+  background-color: #ffffff;
 }
 .jumbotron h1,
 .jumbotron .h1 {
   color: inherit;
 }
 .jumbotron p {
-  margin-bottom: 10px;
-  font-size: 17px;
+  margin-bottom: 15px;
+  font-size: 21px;
   font-weight: 200;
 }
 .container .jumbotron {
-  border-radius: 4px;
+  border-radius: 0px;
 }
 .jumbotron .container {
   max-width: 100%;
 }
 @media screen and (min-width: 768px) {
   .jumbotron {
-    padding-top: 32px;
-    padding-bottom: 32px;
+    padding-top: 48px;
+    padding-bottom: 48px;
   }
   .container .jumbotron {
-    padding-left: 40px;
-    padding-right: 40px;
+    padding-left: 60px;
+    padding-right: 60px;
   }
   .jumbotron h1,
   .jumbotron .h1 {
@@ -4404,9 +4394,9 @@ a.list-group-item.active > .badge,
   padding: 4px;
   margin-bottom: 20px;
   line-height: 1.428571429;
-  background-color: #ffffff;
+  background-color: #f2f2f2;
   border: 1px solid #dddddd;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-transition: all 0.2s ease-in-out;
   transition: all 0.2s ease-in-out;
 }
@@ -4418,7 +4408,7 @@ a.list-group-item.active > .badge,
 a.thumbnail:hover,
 a.thumbnail:focus,
 a.thumbnail.active {
-  border-color: #222222;
+  border-color: #0d8921;
 }
 .thumbnail .caption {
   padding: 9px;
@@ -4428,7 +4418,7 @@ a.thumbnail.active {
   padding: 15px;
   margin-bottom: 20px;
   border: 1px solid transparent;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .alert h4 {
   margin-top: 0;
@@ -4454,45 +4444,45 @@ a.thumbnail.active {
   color: inherit;
 }
 .alert-success {
-  background-color: #eaf6ea;
-  border-color: #bcdfb5;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
   color: #5cb85c;
 }
 .alert-success hr {
-  border-top-color: #acd7a3;
+  border-top-color: #c9e2b3;
 }
 .alert-success .alert-link {
   color: #449d44;
 }
 .alert-info {
-  background-color: #ececec;
-  border-color: #d2d2d2;
-  color: #6c6c6c;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+  color: #5bc0de;
 }
 .alert-info hr {
-  border-top-color: #c5c5c5;
+  border-top-color: #a6e1ec;
 }
 .alert-info .alert-link {
-  color: #525252;
+  color: #31b0d5;
 }
 .alert-warning {
-  background-color: #fef9f3;
-  border-color: #fadac4;
+  background-color: #fcf8e3;
+  border-color: #fbeed5;
   color: #f0ad4e;
 }
 .alert-warning hr {
-  border-top-color: #f8ccac;
+  border-top-color: #f8e5be;
 }
 .alert-warning .alert-link {
   color: #ec971f;
 }
 .alert-danger {
-  background-color: #f9e2e2;
-  border-color: #f0b8c0;
+  background-color: #f2dede;
+  border-color: #eed3d7;
   color: #d9534f;
 }
 .alert-danger hr {
-  border-top-color: #eba3ad;
+  border-top-color: #e6c1c7;
 }
 .alert-danger .alert-link {
   color: #c9302c;
@@ -4518,7 +4508,7 @@ a.thumbnail.active {
   height: 20px;
   margin-bottom: 20px;
   background-color: #f5f5f5;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
   box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
 }
@@ -4553,7 +4543,7 @@ a.thumbnail.active {
   background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
 }
 .progress-bar-info {
-  background-color: #6c6c6c;
+  background-color: #5bc0de;
 }
 .progress-striped .progress-bar-info {
   background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
@@ -4614,13 +4604,13 @@ a.thumbnail.active {
   border: 1px solid #dddddd;
 }
 .list-group-item:first-child {
-  border-top-right-radius: 3px;
-  border-top-left-radius: 3px;
+  border-top-right-radius: 0px;
+  border-top-left-radius: 0px;
 }
 .list-group-item:last-child {
   margin-bottom: 0;
-  border-bottom-right-radius: 3px;
-  border-bottom-left-radius: 3px;
+  border-bottom-right-radius: 0px;
+  border-bottom-left-radius: 0px;
 }
 .list-group-item > .badge {
   float: right;
@@ -4655,11 +4645,11 @@ a.list-group-item.active:focus .list-group-item-heading {
 a.list-group-item.active .list-group-item-text,
 a.list-group-item.active:hover .list-group-item-text,
 a.list-group-item.active:focus .list-group-item-text {
-  color: #71f185;
+  color: #cccccc;
 }
 .list-group-item-success {
   color: #5cb85c;
-  background-color: #eaf6ea;
+  background-color: #dff0d8;
 }
 a.list-group-item-success {
   color: #5cb85c;
@@ -4670,7 +4660,7 @@ a.list-group-item-success .list-group-item-heading {
 a.list-group-item-success:hover,
 a.list-group-item-success:focus {
   color: #5cb85c;
-  background-color: #d8eed8;
+  background-color: #d0e9c6;
 }
 a.list-group-item-success.active,
 a.list-group-item-success.active:hover,
@@ -4680,30 +4670,30 @@ a.list-group-item-success.active:focus {
   border-color: #5cb85c;
 }
 .list-group-item-info {
-  color: #6c6c6c;
-  background-color: #ececec;
+  color: #5bc0de;
+  background-color: #d9edf7;
 }
 a.list-group-item-info {
-  color: #6c6c6c;
+  color: #5bc0de;
 }
 a.list-group-item-info .list-group-item-heading {
   color: inherit;
 }
 a.list-group-item-info:hover,
 a.list-group-item-info:focus {
-  color: #6c6c6c;
-  background-color: #dfdfdf;
+  color: #5bc0de;
+  background-color: #c4e3f3;
 }
 a.list-group-item-info.active,
 a.list-group-item-info.active:hover,
 a.list-group-item-info.active:focus {
   color: #fff;
-  background-color: #6c6c6c;
-  border-color: #6c6c6c;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
 }
 .list-group-item-warning {
   color: #f0ad4e;
-  background-color: #fef9f3;
+  background-color: #fcf8e3;
 }
 a.list-group-item-warning {
   color: #f0ad4e;
@@ -4714,7 +4704,7 @@ a.list-group-item-warning .list-group-item-heading {
 a.list-group-item-warning:hover,
 a.list-group-item-warning:focus {
   color: #f0ad4e;
-  background-color: #fceedb;
+  background-color: #faf2cc;
 }
 a.list-group-item-warning.active,
 a.list-group-item-warning.active:hover,
@@ -4725,7 +4715,7 @@ a.list-group-item-warning.active:focus {
 }
 .list-group-item-danger {
   color: #d9534f;
-  background-color: #f9e2e2;
+  background-color: #f2dede;
 }
 a.list-group-item-danger {
   color: #d9534f;
@@ -4736,7 +4726,7 @@ a.list-group-item-danger .list-group-item-heading {
 a.list-group-item-danger:hover,
 a.list-group-item-danger:focus {
   color: #d9534f;
-  background-color: #f4cecd;
+  background-color: #ebcccc;
 }
 a.list-group-item-danger.active,
 a.list-group-item-danger.active:hover,
@@ -4757,7 +4747,7 @@ a.list-group-item-danger.active:focus {
   margin-bottom: 20px;
   background-color: #ffffff;
   border: 1px solid transparent;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
   box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
 }
@@ -4767,8 +4757,8 @@ a.list-group-item-danger.active:focus {
 .panel-heading {
   padding: 10px 15px;
   border-bottom: 1px solid transparent;
-  border-top-right-radius: 2px;
-  border-top-left-radius: 2px;
+  border-top-right-radius: -1px;
+  border-top-left-radius: -1px;
 }
 .panel-heading > .dropdown .dropdown-toggle {
   color: inherit;
@@ -4786,8 +4776,8 @@ a.list-group-item-danger.active:focus {
   padding: 10px 15px;
   background-color: #f5f5f5;
   border-top: 1px solid #dddddd;
-  border-bottom-right-radius: 2px;
-  border-bottom-left-radius: 2px;
+  border-bottom-right-radius: -1px;
+  border-bottom-left-radius: -1px;
 }
 .panel > .list-group {
   margin-bottom: 0;
@@ -4796,15 +4786,19 @@ a.list-group-item-danger.active:focus {
   border-width: 1px 0;
   border-radius: 0;
 }
-.panel > .list-group:first-child .list-group-item:first-child {
+.panel > .list-group .list-group-item:first-child {
   border-top: 0;
-  border-top-right-radius: 2px;
-  border-top-left-radius: 2px;
 }
-.panel > .list-group:last-child .list-group-item:last-child {
+.panel > .list-group .list-group-item:last-child {
   border-bottom: 0;
-  border-bottom-right-radius: 2px;
-  border-bottom-left-radius: 2px;
+}
+.panel > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: -1px;
+  border-top-left-radius: -1px;
+}
+.panel > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: -1px;
+  border-bottom-left-radius: -1px;
 }
 .panel-heading + .list-group .list-group-item:first-child {
   border-top-width: 0;
@@ -4813,11 +4807,6 @@ a.list-group-item-danger.active:focus {
 .panel > .table-responsive > .table {
   margin-bottom: 0;
 }
-.panel > .table:first-child,
-.panel > .table-responsive:first-child > .table:first-child {
-  border-top-right-radius: 2px;
-  border-top-left-radius: 2px;
-}
 .panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
 .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
 .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
@@ -4826,7 +4815,7 @@ a.list-group-item-danger.active:focus {
 .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
 .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
 .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
-  border-top-left-radius: 2px;
+  border-top-left-radius: -1px;
 }
 .panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
 .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
@@ -4836,12 +4825,7 @@ a.list-group-item-danger.active:focus {
 .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
 .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
 .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
-  border-top-right-radius: 2px;
-}
-.panel > .table:last-child,
-.panel > .table-responsive:last-child > .table:last-child {
-  border-bottom-right-radius: 2px;
-  border-bottom-left-radius: 2px;
+  border-top-right-radius: -1px;
 }
 .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
 .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
@@ -4851,7 +4835,7 @@ a.list-group-item-danger.active:focus {
 .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
 .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
 .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
-  border-bottom-left-radius: 2px;
+  border-bottom-left-radius: -1px;
 }
 .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
 .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
@@ -4861,7 +4845,7 @@ a.list-group-item-danger.active:focus {
 .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
 .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
 .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
-  border-bottom-right-radius: 2px;
+  border-bottom-right-radius: -1px;
 }
 .panel > .panel-body + .table,
 .panel > .panel-body + .table-responsive {
@@ -4932,7 +4916,7 @@ a.list-group-item-danger.active:focus {
 }
 .panel-group .panel {
   margin-bottom: 0;
-  border-radius: 3px;
+  border-radius: 0px;
   overflow: hidden;
 }
 .panel-group .panel + .panel {
@@ -4979,60 +4963,60 @@ a.list-group-item-danger.active:focus {
   border-bottom-color: #0d8921;
 }
 .panel-success {
-  border-color: #bcdfb5;
+  border-color: #d6e9c6;
 }
 .panel-success > .panel-heading {
   color: #5cb85c;
-  background-color: #eaf6ea;
-  border-color: #bcdfb5;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
 }
 .panel-success > .panel-heading + .panel-collapse .panel-body {
-  border-top-color: #bcdfb5;
+  border-top-color: #d6e9c6;
 }
 .panel-success > .panel-footer + .panel-collapse .panel-body {
-  border-bottom-color: #bcdfb5;
+  border-bottom-color: #d6e9c6;
 }
 .panel-info {
-  border-color: #d2d2d2;
+  border-color: #bce8f1;
 }
 .panel-info > .panel-heading {
-  color: #6c6c6c;
-  background-color: #ececec;
-  border-color: #d2d2d2;
+  color: #5bc0de;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
 }
 .panel-info > .panel-heading + .panel-collapse .panel-body {
-  border-top-color: #d2d2d2;
+  border-top-color: #bce8f1;
 }
 .panel-info > .panel-footer + .panel-collapse .panel-body {
-  border-bottom-color: #d2d2d2;
+  border-bottom-color: #bce8f1;
 }
 .panel-warning {
-  border-color: #fadac4;
+  border-color: #fbeed5;
 }
 .panel-warning > .panel-heading {
   color: #f0ad4e;
-  background-color: #fef9f3;
-  border-color: #fadac4;
+  background-color: #fcf8e3;
+  border-color: #fbeed5;
 }
 .panel-warning > .panel-heading + .panel-collapse .panel-body {
-  border-top-color: #fadac4;
+  border-top-color: #fbeed5;
 }
 .panel-warning > .panel-footer + .panel-collapse .panel-body {
-  border-bottom-color: #fadac4;
+  border-bottom-color: #fbeed5;
 }
 .panel-danger {
-  border-color: #f0b8c0;
+  border-color: #eed3d7;
 }
 .panel-danger > .panel-heading {
   color: #d9534f;
-  background-color: #f9e2e2;
-  border-color: #f0b8c0;
+  background-color: #f2dede;
+  border-color: #eed3d7;
 }
 .panel-danger > .panel-heading + .panel-collapse .panel-body {
-  border-top-color: #f0b8c0;
+  border-top-color: #eed3d7;
 }
 .panel-danger > .panel-footer + .panel-collapse .panel-body {
-  border-bottom-color: #f0b8c0;
+  border-bottom-color: #eed3d7;
 }
 .well {
   min-height: 20px;
@@ -5040,7 +5024,7 @@ a.list-group-item-danger.active:focus {
   margin-bottom: 20px;
   background-color: #f5f5f5;
   border: 1px solid #e3e3e3;
-  border-radius: 3px;
+  border-radius: 0px;
   -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
   box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
 }
@@ -5050,11 +5034,11 @@ a.list-group-item-danger.active:focus {
 }
 .well-lg {
   padding: 24px;
-  border-radius: 4px;
+  border-radius: 0px;
 }
 .well-sm {
   padding: 9px;
-  border-radius: 2px;
+  border-radius: 0px;
 }
 .close {
   float: right;
@@ -5121,7 +5105,7 @@ button.close {
   background-color: #ffffff;
   border: 1px solid #999999;
   border: 1px solid rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
+  border-radius: 0px;
   -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
   box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
   background-clip: padding-box;
@@ -5231,7 +5215,7 @@ button.close {
   text-align: center;
   text-decoration: none;
   background-color: #000000;
-  border-radius: 3px;
+  border-radius: 0px;
 }
 .tooltip-arrow {
   position: absolute;
@@ -5305,7 +5289,7 @@ button.close {
   background-clip: padding-box;
   border: 1px solid #cccccc;
   border: 1px solid rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
+  border-radius: 0px;
   -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
   box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
   white-space: normal;
@@ -5570,8 +5554,8 @@ button.close {
   text-shadow: none;
 }
 @media screen and (min-width: 768px) {
-  .carousel-control .glyphicon-chevron-left,
-  .carousel-control .glyphicon-chevron-right,
+  .carousel-control .glyphicons-chevron-left,
+  .carousel-control .glyphicons-chevron-right,
   .carousel-control .icon-prev,
   .carousel-control .icon-next {
     width: 30px;
diff --git a/share/nitdoc/css/nitdoc.cards.css b/share/nitdoc/css/nitdoc.cards.css
new file mode 100644 (file)
index 0000000..fc3e5ef
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/* cards */
+
+.card.active {
+       border: 1px solid #1E9431;
+}
+
+.card-heading {
+    margin-top: 0;
+    margin-bottom: 5px;
+}
+
+.card {
+       display: table;
+       width: 100%;
+       background: #fff;
+       border: 1px solid #eee;
+       margin-top: 10px;
+       box-shadow: -1px -1px 3px rgba(0,0,0,.06), 1px 1px 3px rgba(0,0,0,.12);
+}
+
+.card-body, .card-left, .card-right {
+       display: table-cell;
+       padding: 15px;
+}
+
+.card-body {
+       padding: 15px 0;
+       width: 100%
+}
+
+.card-body:first-child {
+       padding-left: 15px;
+}
+
+.card-body:last-child {
+       padding-right: 15px;
+}
+
+.card-list {
+       margin-top: 10px;
+}
+
+.card-list > .card:first-child {
+       border-top: 1px solid #ddd;
+}
+
+.card-list > .card {
+       margin-top: 0;
+       border-top: none;
+}
+
+.card-title {
+    margin-top: 0;
+}
diff --git a/share/nitdoc/css/nitdoc.code.css b/share/nitdoc/css/nitdoc.code.css
new file mode 100644 (file)
index 0000000..2a944aa
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+/* Code Highlighting */
+
+.nitcode a { color: inherit; text-decoration: inherit; } /* hide links */
+.nitcode a:hover { text-decoration: underline; } /* underline links */
+
+/* lexical raw tokens. independent of usage or semantic: */
+.nitcode .nc_c { color: gray; font-style: italic; } /* comment */
+.nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
+.nitcode .nc_k { font-weight: bold; } /* keyword */
+.nitcode .nc_o {} /* operator */
+.nitcode .nc_i {} /* standard identifier */
+.nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
+.nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
+.nitcode .nc_l { color: #009999; } /* char and number literal */
+.nitcode .nc_s { color: #8F1546; } /* string literal */
+
+/* syntactic token usage. added because of their position in the AST */
+.nitcode .nc_ast { color: blue; } /* assert label */
+.nitcode .nc_la { color: blue; } /* break/continue label */
+.nitcode .nc_m { color: #445588; } /* module name */
+
+/* syntactic groups */
+.nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
+.nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
+.nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
+.nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
+.nitcode .nc_cdef {} /* A whole class definition */
+.nitcode .nc_pdef {} /* A whole property definition */
+
+/* semantic token usage */
+.nitcode .nc_v { font-style: italic; } /* local variable or parameter */
+.nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
+.nitcode .nc_error { border: 1px red solid;} /* not used */
index 01da471..81153c7 100644 (file)
 /*
- * Global
+ * 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.
  */
 
-body {
-       text-align: justify;
-}
-
-a:hover {
-       text-decoration: none;
-}
-
-ul li .label {
-       padding: 1px 4px;
-       font-size: 70%;
-       vertical-align: middle;
-       border-radius: .25em;
-       margin: 3px;
-       font-family: monospace;
-}
-
-code {
-       color: #333;
-       border: 1px solid #ddd;
-}
+/* Top menu */
 
-pre code {
-       border: none;
+.navbar-fixed-top {
+       background-color: #1E9431;
+       box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28);
 }
 
-.navbar-default .navbar-toggle {
-       margin-top: 2px;
-       padding: 5px 10px;
+.navbar-brand > a {
+       color: #fff;
 }
 
-h3 {
-       margin: 10px 0;
+.container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse {
+    margin-right: auto;
+    margin-left: auto;
 }
 
-article {
-       padding: 10px 0px;
+.navbar-default .navbar-collapse, .navbar-default .navbar-form {
+       border-color: transparent;
 }
 
-article.nospace {
-       padding: 0;
-       margin: 0;
+.navbar-toggle {
+       float: left;
 }
 
-/*
- * Sidebar
- */
+/* Body */
 
-#sidebar .panel {
-       margin-top: 15px;
-       box-shadow: none;
-}
-
-#sidebar .panel-heading {
-       padding: 3px 0 0 0;
-       font-size: 16px;
-}
-
-#sidebar .panel-body {
-       padding: 0;
-}
-
-#sidebar .panel-body ul>li>a {
-       padding: 0;
-}
-
-#sidebar .panel-body ul>li {
-       padding: 0 0 0 15px;
-       font-size: 15px;
-       color: #333;
+body {
+       background: #f2f2f2;
+       margin-top: 70px;
+       margin-bottom: 70px;
 }
 
-#sidebar .panel-body ul ul>li,
-#sidebar .panel-body ul ul>li a {
-       padding: 0 0 0 0;
-       font-size: 14px;
+h1, h2, h3, h4, h5, h6 {
        color: #666;
 }
 
-#sidebar .panel-body ul ul ul>li {
-       font-size: 13px;
-       color: #999;
+.page-header {
+    margin-top: 0;
+    border: none;
 }
 
-#sidebar .panel-heading a:hover, #sidebar .panel ul a:hover {
-       color: #0d8921;
-       background-color: transparent;
-}
-
-#sidebar .summary .nav>li>a {
-       padding: 3px 0 0 10px;
-       font-size: 15px;
-       border-left: 2px solid transparent;
-       color: #333;
-}
+#sidebar { margin-top: 15px; }
 
-#sidebar .summary .nav .nav>li>a {
-       padding-top: 2px;
-       padding-left: 15px;
-       font-size: 14px;
-       color: #666;
+pre {
+       white-space: pre-wrap;
 }
 
-#sidebar .summary .nav .nav .nav>li>a {
-       padding-left: 20px;
-       font-size: 13px;
+.footer {
        color: #999;
+       text-align: center;
+       padding: 10px;
+       margin: 20px 0;
 }
 
-#sidebar .summary .nav .nav .nav .nav>li>a {
-       font-size: 12px;
-       color: #CCC;
-}
-
-#sidebar .summary .nav>.active>a,
-#sidebar .summary .nav>.active>a:hover,
-#sidebar .summary .nav>li>a:hover {
-       color: #0d8921;
-       background-color: transparent;
-}
-
-#sidebar .summary .nav>.active>a,
-#sidebar .summary .nav>.active>a:hover,
-#sidebar .summary .nav .nav>.active>a,
-#sidebar .summary .nav .nav>.active>a:hover,
-#sidebar .summary .nav .nav .nav>.active>a,
-#sidebar .summary .nav .nav .nav>.active>a:hover {
-       color: #0d8921;
-       border-left: 2px solid #0d8921;
-       margin-left: 0px;
-}
-
-#sidebar .summary .nav>li>a:hover,
-#sidebar .summary .nav .nav>li>a:hover,
-#sidebar .summary .nav .nav .nav>li>a:hover {
-       color: #0d8921;
-       border-left: 1px solid #0d8921;
-       margin-left: 1px;
-       background-color: transparent;
-}
-
-/*
- * Content
- */
-
-#content {
-       position: fixed;
-       top: 30px;
-       bottom: 0;
-       left: 10px;
-       right: 15px;
-}
-
-#content>.col {
-       height: 100%;
-       overflow-y: scroll;
-}
-
-#content>.col::-webkit-scrollbar-thumb {
-       background: transparent;
-}
+/* ui */
 
-#content>.col:hover::-webkit-scrollbar-thumb {
-       background: #CCC;
-       -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,0.10),inset 0 -1px 0 rgba(0,0,0,0.07);
-}
+.btn-bar { margin-top: -5px; float: right }
+.btn-bar .btn { padding: 5px 10px; }
 
-#content>.col::-webkit-scrollbar {
-    width: 7px;
-       height: 7px;
-}
+/* Doc */
 
-#content>.col::-webkit-scrollbar-thumb:hover {
-       background: #999;
+.nitdoc > *:first-child {
+       margin-top: 0;
 }
 
-#content>.col::-webkit-scrollbar-corner {
-       background: transparent;
+.signature {
+       color: #777;
+       font-family: monospace;
 }
 
-#content>.col::-webkit-scrollbar-button {
-       width: 0;
-       height: 0;
-       display: none;
+.signature .name {
+       font-weight: bold;
 }
 
-#content article:target {
-       padding-left: 10px;
-       margin-left: -10px;
-       border-left: 2px solid #0d8921;
+.page-header .signature .name, .signature .signature .name {
+       font-weight: normal;
 }
 
+/* Summary */
 
-.pull-right .dropdown-toggle {
-       padding: 0 5px;
-}
-
-/* Hide the "..." link */
+.summary h1 { font-size: 14px; margin: 10px 0 5px 0;   font-weight: bold; }
+.summary h2 { font-size: 13px; margin:  9px 0 5px 5px; font-weight: bold; }
+.summary h3 { font-size: 12px; margin:  8px 0 5px 10px; }
+.summary h4 { font-size: 11px; margin:  7px 0 5px 15px; }
+.summary h5 { font-size: 10px; margin:  6px 0 5px 20px; }
+.summary h6 { font-size:  9px; margin:  5px 0 5px 25px; }
 
-article .dropdown, article .dropdown {
-       visibility: hidden;
-}
-article:hover .dropdown, article:target .dropdown {
-       visibility: visible;
-}
+.summary a, .summary a:hover { color: #666; }
 
 /*
- * Page parts
+ * Nit
  */
 
-.footer {
-       padding: 10px;
-       margin: 20px 0;
-}
-
-.subtitle {
-       margin-bottom: 10px;
-}
-
-.label:empty {
-       display:inline;
-}
-
-.label.intro:before {
-       content: "I";
-}
-.label.redef:before {
-       content: "R";
-}
-.label.inherit:before {
-       content: "H";
-}
-
-.signature span.glyphicon {
-       margin: 0 10px 5px 0;
-       font-size: 55%;
-       vertical-align: middle;
-}
-
-.signature a, .list-definition a, .info.signature a {
-       color: #0d8921;
-}
-
-.info {
-       color: #888;
-}
-
-.info a {
-       color: #666;
-}
-
-.info a:hover {
+.nitdoc h1, .nitdoc h2, .nitdoc h3, .nitdoc h4, .nitdoc h5, .nitdoc h6 {
        color: #333;
 }
 
-.graph {
-       text-align: center;
-}
-
 .nitdoc .synopsys {
-       margin: 5px 0;
-       font-size: 16px;
-       font-weight: bold;
-       line-height: 1.4;
+       margin-top: 0;
 }
 
 .public {
@@ -279,41 +124,3 @@ article:hover .dropdown, article:target .dropdown {
 .private {
        color: #a94442;
 }
-
-.list-definition .list-definition {
-       margin-left: 30px;
-}
-
-/*
- * Code Highlighting
- */
-
-.nitcode a { color: inherit; text-decoration: inherit; } /* hide links */
-.nitcode a:hover { text-decoration: underline; } /* underline links */
-.nitcode span[title]:hover { text-decoration: underline; } /* underline titles */
-/* lexical raw tokens. independent of usage or semantic: */
-.nitcode .nc_c { color: gray; font-style: italic; } /* comment */
-.nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
-.nitcode .nc_k { font-weight: bold; } /* keyword */
-.nitcode .nc_o {} /* operator */
-.nitcode .nc_i {} /* standard identifier */
-.nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
-.nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
-.nitcode .nc_l { color: #009999; } /* char and number literal */
-.nitcode .nc_s { color: #8F1546; } /* string literal */
-/* syntactic token usage. added because of their position in the AST */
-.nitcode .nc_ast { color: blue; } /* assert label */
-.nitcode .nc_la { color: blue; } /* break/continue label */
-.nitcode .nc_m { color: #445588; } /* module name */
-/* syntactic groups */
-.nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
-.nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
-.nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
-.nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
-.nitcode .nc_cdef {} /* A whole class definition */
-.nitcode .nc_pdef {} /* A whole property definition */
-/* semantic token usage */
-.nitcode .nc_v { font-style: italic; } /* local variable or parameter */
-.nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
-.nitcode .nc_error { border: 1px red solid;} /* not used */
-
diff --git a/share/nitdoc/css/nitdoc.quicksearch.css b/share/nitdoc/css/nitdoc.quicksearch.css
new file mode 100644 (file)
index 0000000..3e306c3
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+/* Nitdoc Quick Search JS module */
+
+.has-icon {
+    position: relative;
+}
+
+.has-icon .form-control {
+       padding-left: 35px;
+}
+
+.form-control-icon {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    display: block;
+    width: 34px;
+    height: 34px;
+    line-height: 34px;
+    text-align: center;
+    pointer-events: none;
+}
+
+.navbar-fixed-top .form-control:hover, .navbar-fixed-top .form-control:focus {
+       background: rgba(255, 255, 255, 0.2);
+}
+
+.navbar-fixed-top .form-control {
+       background: rgba(255, 255, 255, 0.1);
+    border: none;
+    color: #fff;
+    box-shadow: none;
+}
+
+.navbar-fixed-top .form-control-icon {
+       color: #fff;
+}
+
+.navbar-fixed-top .form-group {
+       margin-top: 8px;
+       margin-bottom: 0px;
+}
+
+.navbar-fixed-top *::-webkit-input-placeholder { color: #fff; }
+.navbar-fixed-top *:-moz-placeholder { color: #fff; }
+.navbar-fixed-top *::-moz-placeholder { color: #fff; }
+.navbar-fixed-top *:-ms-input-placeholder { color: #fff; }
+
+.search-input {
+       width: 100%;
+}
+
+#nitdoc-qs-popup {
+       background-color: #FFFFFF;
+       border: 1px solid #E0E0E0;
+       z-index: 1000;
+       -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
+       -moz-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
+       box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
+}
+
+.qs-card {
+       cursor: pointer;
+       padding: 5px;
+       border-bottom: 1px solid #F0F0F0;
+       overflow: hidden;
+}
+
+.qs-card h1 {
+       color: #0D8921;
+       font-size: 1.2em;
+       margin-top: 5px;
+       margin-bottom: 0;
+}
+
+.qs-info {
+       color: #6C6C6C;
+       font-size: smaller;
+}
+
+.qs-noresult {
+       color: #6C6C6C;
+       font-size: small;
+}
+
+.qs-overflow {
+       text-align: center;
+       font-size:      x-small;
+       color: #6C6C6C;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -khtml-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.qs-overflow-active {
+       color: #0D8921;
+       cursor: pointer;
+}
+
+.qs-overflow-active:hover {
+       background-color: #E0E0E0;
+}
+
+.qs-active {
+       background: #EEE;
+}
diff --git a/share/nitdoc/js/lib/github-api.js b/share/nitdoc/js/lib/github-api.js
deleted file mode 100644 (file)
index f03188a..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/* \r
- * GitHub API wrapper for github plugin\r
- */\r
-define([\r
-       "jquery",\r
-       "utils"\r
-], function($, Utils) {\r
-       return {\r
-\r
-               // try to login the user to github API\r
-               login: function(user) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "GET",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo,\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function() {\r
-                                       res = true;\r
-                               }\r
-                       });\r
-                       user.infos = this.getUserInfos(user);\r
-                       user.signedOff = this.getSignedOff(user)\r
-                       return res;\r
-               },\r
-\r
-               // request for user github account infos\r
-               getUserInfos: function(user) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "GET",\r
-                                       url: "https://api.github.com/users/" + user.login,\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // build signedoff user default signature\r
-               getSignedOff: function(user) {\r
-                       return user.infos.name + " <" + user.infos.email + ">";\r
-               },\r
-\r
-               // get the branches list from a repo\r
-               getBranches: function(user) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "GET",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/branches",\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               /* GitHub commits */\r
-\r
-               // get the latest commit on `branchName`\r
-               getCommit: function(user, sha) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "GET",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits/" + sha,\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // get the base tree for a commit sha\r
-               getTree: function(user, sha) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "GET",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees/" + sha + "?recursive=1",\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // create a new blob\r
-               createBlob: function(user, content) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "POST",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/blobs",\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               data: JSON.stringify({\r
-                                       content: content.base64Encode(),\r
-                                       encoding: "base64"\r
-                               }),\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // create a new tree from a base tree\r
-               createTree: function(user, baseTree, path, blob) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "POST",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees",\r
-                               data: JSON.stringify({\r
-                                       base_tree: baseTree.sha,\r
-                                       tree: [{\r
-                                               path: path,\r
-                                               mode: "100644", // file (blob)\r
-                                               type: "blob",\r
-                                               sha: blob.sha\r
-                                       }]\r
-                               }),\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // create a new commit\r
-               createCommit: function(user, message, parentCommit, tree) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "POST",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits",\r
-                               data: JSON.stringify({\r
-                                       message: message,\r
-                                       parents: parentCommit,\r
-                                       tree: tree.sha,\r
-                               }),\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // create a pull request\r
-               createPullRequest: function(user, title, body, origin, head) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "POST",\r
-                               url: "https://api.github.com/repos/" + origin.user + "/" + origin.repo + "/pulls",\r
-                               data: JSON.stringify({\r
-                                       title: title,\r
-                                       body: body,\r
-                                       base: origin.branch,\r
-                                       head: user.login + ":" + head\r
-                               }),\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               // update a pull request\r
-               updatePullRequest: function(user, title, body, state, request) {\r
-                       var res = false;\r
-                               $.ajax({\r
-                               beforeSend: function (xhr) {\r
-                                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                               },\r
-                               type: "PATCH",\r
-                               url: request.url,\r
-                               data: JSON.stringify({\r
-                                       title: title,\r
-                                       body: body,\r
-                                       state: state\r
-                               }),\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               },\r
-\r
-               /* Files */\r
-\r
-               getFile: function(user, path, branch) {\r
-                       var res = false;\r
-                       $.ajax({\r
-                               type: "GET",\r
-                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/contents/" + path,\r
-                               data: {\r
-                                       ref: branch\r
-                               },\r
-                               async: false,\r
-                               dataType: 'json',\r
-                               success: function(response) {\r
-                                       res = response;\r
-                               },\r
-                               error: function(response) {\r
-                                       res = response;\r
-                               }\r
-                       });\r
-                       return res;\r
-               }\r
-       }\r
-});\r
diff --git a/share/nitdoc/js/lib/highlight.js b/share/nitdoc/js/lib/highlight.js
deleted file mode 100644 (file)
index bd277ee..0000000
+++ /dev/null
@@ -1,715 +0,0 @@
-/*     Copyright (c) 2006, Ivan Sagalaev
-       All rights reserved.
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are met:
-
-               * Redistributions of source code must retain the above copyright
-                 notice, this list of conditions and the following disclaimer.
-               * Redistributions in binary form must reproduce the above copyright
-                 notice, this list of conditions and the following disclaimer in the
-                 documentation and/or other materials provided with the distribution.
-               * Neither the name of highlight.js nor the names of its contributors
-                 may be used to endorse or promote products derived from this software
-                 without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-       DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-var hljs = new function() {
-
-  /* Utility functions */
-
-  function escape(value) {
-       return value.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;');
-  }
-
-  function tag(node) {
-       return node.nodeName.toLowerCase();
-  }
-
-  function testRe(re, lexeme) {
-       var match = re && re.exec(lexeme);
-       return match && match.index == 0;
-  }
-
-  function blockLanguage(block) {
-       var classes = (block.className + ' ' + (block.parentNode ? block.parentNode.className : '')).split(/\s+/);
-       classes = classes.map(function(c) {return c.replace(/^lang(uage)?-/, '');});
-       return classes.filter(function(c) {return getLanguage(c) || c == 'no-highlight';})[0];
-  }
-
-  function inherit(parent, obj) {
-       var result = {};
-       for (var key in parent)
-         result[key] = parent[key];
-       if (obj)
-         for (var key in obj)
-           result[key] = obj[key];
-       return result;
-  };
-
-  /* Stream merging */
-
-  function nodeStream(node) {
-       var result = [];
-       (function _nodeStream(node, offset) {
-         for (var child = node.firstChild; child; child = child.nextSibling) {
-           if (child.nodeType == 3)
-             offset += child.nodeValue.length;
-           else if (tag(child) == 'br')
-             offset += 1;
-           else if (child.nodeType == 1) {
-             result.push({
-               event: 'start',
-               offset: offset,
-               node: child
-             });
-             offset = _nodeStream(child, offset);
-             result.push({
-               event: 'stop',
-               offset: offset,
-               node: child
-             });
-           }
-         }
-         return offset;
-       })(node, 0);
-       return result;
-  }
-
-  function mergeStreams(original, highlighted, value) {
-       var processed = 0;
-       var result = '';
-       var nodeStack = [];
-
-       function selectStream() {
-         if (!original.length || !highlighted.length) {
-           return original.length ? original : highlighted;
-         }
-         if (original[0].offset != highlighted[0].offset) {
-           return (original[0].offset < highlighted[0].offset) ? original : highlighted;
-         }
-
-         /*
-         To avoid starting the stream just before it should stop the order is
-         ensured that original always starts first and closes last:
-
-         if (event1 == 'start' && event2 == 'start')
-           return original;
-         if (event1 == 'start' && event2 == 'stop')
-           return highlighted;
-         if (event1 == 'stop' && event2 == 'start')
-           return original;
-         if (event1 == 'stop' && event2 == 'stop')
-           return highlighted;
-
-         ... which is collapsed to:
-         */
-         return highlighted[0].event == 'start' ? original : highlighted;
-       }
-
-       function open(node) {
-         function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value) + '"';}
-         result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>';
-       }
-
-       function close(node) {
-         result += '</' + tag(node) + '>';
-       }
-
-       function render(event) {
-         (event.event == 'start' ? open : close)(event.node);
-       }
-
-       while (original.length || highlighted.length) {
-         var stream = selectStream();
-         result += escape(value.substr(processed, stream[0].offset - processed));
-         processed = stream[0].offset;
-         if (stream == original) {
-           /*
-           On any opening or closing tag of the original markup we first close
-           the entire highlighted node stack, then render the original tag along
-           with all the following original tags at the same offset and then
-           reopen all the tags on the highlighted stack.
-           */
-           nodeStack.reverse().forEach(close);
-           do {
-             render(stream.splice(0, 1)[0]);
-             stream = selectStream();
-           } while (stream == original && stream.length && stream[0].offset == processed);
-           nodeStack.reverse().forEach(open);
-         } else {
-           if (stream[0].event == 'start') {
-             nodeStack.push(stream[0].node);
-           } else {
-             nodeStack.pop();
-           }
-           render(stream.splice(0, 1)[0]);
-         }
-       }
-       return result + escape(value.substr(processed));
-  }
-
-  /* Initialization */
-
-  function compileLanguage(language) {
-
-       function reStr(re) {
-           return (re && re.source) || re;
-       }
-
-       function langRe(value, global) {
-         return RegExp(
-           reStr(value),
-           'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '')
-         );
-       }
-
-       function compileMode(mode, parent) {
-         if (mode.compiled)
-           return;
-         mode.compiled = true;
-
-         mode.keywords = mode.keywords || mode.beginKeywords;
-         if (mode.keywords) {
-           var compiled_keywords = {};
-
-           function flatten(className, str) {
-             if (language.case_insensitive) {
-               str = str.toLowerCase();
-             }
-             str.split(' ').forEach(function(kw) {
-               var pair = kw.split('|');
-               compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1];
-             });
-           }
-
-           if (typeof mode.keywords == 'string') { // string
-             flatten('keyword', mode.keywords);
-           } else {
-             Object.keys(mode.keywords).forEach(function (className) {
-               flatten(className, mode.keywords[className]);
-             });
-           }
-           mode.keywords = compiled_keywords;
-         }
-         mode.lexemesRe = langRe(mode.lexemes || /\b[A-Za-z0-9_]+\b/, true);
-
-         if (parent) {
-           if (mode.beginKeywords) {
-             mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\b';
-           }
-           if (!mode.begin)
-             mode.begin = /\B|\b/;
-           mode.beginRe = langRe(mode.begin);
-           if (!mode.end && !mode.endsWithParent)
-             mode.end = /\B|\b/;
-           if (mode.end)
-             mode.endRe = langRe(mode.end);
-           mode.terminator_end = reStr(mode.end) || '';
-           if (mode.endsWithParent && parent.terminator_end)
-             mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end;
-         }
-         if (mode.illegal)
-           mode.illegalRe = langRe(mode.illegal);
-         if (mode.relevance === undefined)
-           mode.relevance = 1;
-         if (!mode.contains) {
-           mode.contains = [];
-         }
-         var expanded_contains = [];
-         mode.contains.forEach(function(c) {
-           if (c.variants) {
-             c.variants.forEach(function(v) {expanded_contains.push(inherit(c, v));});
-           } else {
-             expanded_contains.push(c == 'self' ? mode : c);
-           }
-         });
-         mode.contains = expanded_contains;
-         mode.contains.forEach(function(c) {compileMode(c, mode);});
-
-         if (mode.starts) {
-           compileMode(mode.starts, parent);
-         }
-
-         var terminators =
-           mode.contains.map(function(c) {
-             return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin;
-           })
-           .concat([mode.terminator_end, mode.illegal])
-           .map(reStr)
-           .filter(Boolean);
-         mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(s) {return null;}};
-
-         mode.continuation = {};
-       }
-
-       compileMode(language);
-  }
-
-  /*
-  Core highlighting function. Accepts a language name, or an alias, and a
-  string with the code to highlight. Returns an object with the following
-  properties:
-
-  - relevance (int)
-  - value (an HTML string with highlighting markup)
-
-  */
-  function highlight(name, value, ignore_illegals, continuation) {
-
-       function subMode(lexeme, mode) {
-         for (var i = 0; i < mode.contains.length; i++) {
-           if (testRe(mode.contains[i].beginRe, lexeme)) {
-             return mode.contains[i];
-           }
-         }
-       }
-
-       function endOfMode(mode, lexeme) {
-         if (testRe(mode.endRe, lexeme)) {
-           return mode;
-         }
-         if (mode.endsWithParent) {
-           return endOfMode(mode.parent, lexeme);
-         }
-       }
-
-       function isIllegal(lexeme, mode) {
-         return !ignore_illegals && testRe(mode.illegalRe, lexeme);
-       }
-
-       function keywordMatch(mode, match) {
-         var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];
-         return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str];
-       }
-
-       function buildSpan(classname, insideSpan, leaveOpen, noPrefix) {
-         var classPrefix = noPrefix ? '' : options.classPrefix,
-             openSpan    = '<span class="' + classPrefix,
-             closeSpan   = leaveOpen ? '' : '</span>';
-
-         openSpan += classname + '">';
-
-         return openSpan + insideSpan + closeSpan;
-       }
-
-       function processKeywords() {
-         if (!top.keywords)
-           return escape(mode_buffer);
-         var result = '';
-         var last_index = 0;
-         top.lexemesRe.lastIndex = 0;
-         var match = top.lexemesRe.exec(mode_buffer);
-         while (match) {
-           result += escape(mode_buffer.substr(last_index, match.index - last_index));
-           var keyword_match = keywordMatch(top, match);
-           if (keyword_match) {
-             relevance += keyword_match[1];
-             result += buildSpan(keyword_match[0], escape(match[0]));
-           } else {
-             result += escape(match[0]);
-           }
-           last_index = top.lexemesRe.lastIndex;
-           match = top.lexemesRe.exec(mode_buffer);
-         }
-         return result + escape(mode_buffer.substr(last_index));
-       }
-
-       function processSubLanguage() {
-         if (top.subLanguage && !languages[top.subLanguage]) {
-           return escape(mode_buffer);
-         }
-         var result = top.subLanguage ? highlight(top.subLanguage, mode_buffer, true, top.continuation.top) : highlightAuto(mode_buffer);
-         // Counting embedded language score towards the host language may be disabled
-         // with zeroing the containing mode relevance. Usecase in point is Markdown that
-         // allows XML everywhere and makes every XML snippet to have a much larger Markdown
-         // score.
-         if (top.relevance > 0) {
-           relevance += result.relevance;
-         }
-         if (top.subLanguageMode == 'continuous') {
-           top.continuation.top = result.top;
-         }
-         return buildSpan(result.language, result.value, false, true);
-       }
-
-       function processBuffer() {
-         return top.subLanguage !== undefined ? processSubLanguage() : processKeywords();
-       }
-
-       function startNewMode(mode, lexeme) {
-         var markup = mode.className? buildSpan(mode.className, '', true): '';
-         if (mode.returnBegin) {
-           result += markup;
-           mode_buffer = '';
-         } else if (mode.excludeBegin) {
-           result += escape(lexeme) + markup;
-           mode_buffer = '';
-         } else {
-           result += markup;
-           mode_buffer = lexeme;
-         }
-         top = Object.create(mode, {parent: {value: top}});
-       }
-
-       function processLexeme(buffer, lexeme) {
-
-         mode_buffer += buffer;
-         if (lexeme === undefined) {
-           result += processBuffer();
-           return 0;
-         }
-
-         var new_mode = subMode(lexeme, top);
-         if (new_mode) {
-           result += processBuffer();
-           startNewMode(new_mode, lexeme);
-           return new_mode.returnBegin ? 0 : lexeme.length;
-         }
-
-         var end_mode = endOfMode(top, lexeme);
-         if (end_mode) {
-           var origin = top;
-           if (!(origin.returnEnd || origin.excludeEnd)) {
-             mode_buffer += lexeme;
-           }
-           result += processBuffer();
-           do {
-             if (top.className) {
-               result += '</span>';
-             }
-             relevance += top.relevance;
-             top = top.parent;
-           } while (top != end_mode.parent);
-           if (origin.excludeEnd) {
-             result += escape(lexeme);
-           }
-           mode_buffer = '';
-           if (end_mode.starts) {
-             startNewMode(end_mode.starts, '');
-           }
-           return origin.returnEnd ? 0 : lexeme.length;
-         }
-
-         if (isIllegal(lexeme, top))
-           throw new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
-
-         /*
-         Parser should not reach this point as all types of lexemes should be caught
-         earlier, but if it does due to some bug make sure it advances at least one
-         character forward to prevent infinite looping.
-         */
-         mode_buffer += lexeme;
-         return lexeme.length || 1;
-       }
-
-       var language = getLanguage(name);
-       if (!language) {
-         throw new Error('Unknown language: "' + name + '"');
-       }
-
-       compileLanguage(language);
-       var top = continuation || language;
-       var result = '';
-       for(var current = top; current != language; current = current.parent) {
-         if (current.className) {
-           result += buildSpan(current.className, result, true);
-         }
-       }
-       var mode_buffer = '';
-       var relevance = 0;
-       try {
-         var match, count, index = 0;
-         while (true) {
-           top.terminators.lastIndex = index;
-           match = top.terminators.exec(value);
-           if (!match)
-             break;
-           count = processLexeme(value.substr(index, match.index - index), match[0]);
-           index = match.index + count;
-         }
-         processLexeme(value.substr(index));
-         for(var current = top; current.parent; current = current.parent) { // close dangling modes
-           if (current.className) {
-             result += '</span>';
-           }
-         };
-         return {
-           relevance: relevance,
-           value: result,
-           language: name,
-           top: top
-         };
-       } catch (e) {
-         if (e.message.indexOf('Illegal') != -1) {
-           return {
-             relevance: 0,
-             value: escape(value)
-           };
-         } else {
-           throw e;
-         }
-       }
-  }
-
-  /*
-  Highlighting with language detection. Accepts a string with the code to
-  highlight. Returns an object with the following properties:
-
-  - language (detected language)
-  - relevance (int)
-  - value (an HTML string with highlighting markup)
-  - second_best (object with the same structure for second-best heuristically
-       detected language, may be absent)
-
-  */
-  function highlightAuto(text, languageSubset) {
-       languageSubset = languageSubset || options.languages || Object.keys(languages);
-       var result = {
-         relevance: 0,
-         value: escape(text)
-       };
-       var second_best = result;
-       languageSubset.forEach(function(name) {
-         if (!getLanguage(name)) {
-           return;
-         }
-         var current = highlight(name, text, false);
-         current.language = name;
-         if (current.relevance > second_best.relevance) {
-           second_best = current;
-         }
-         if (current.relevance > result.relevance) {
-           second_best = result;
-           result = current;
-         }
-       });
-       if (second_best.language) {
-         result.second_best = second_best;
-       }
-       return result;
-  }
-
-  /*
-  Post-processing of the highlighted markup:
-
-  - replace TABs with something more useful
-  - replace real line-breaks with '<br>' for non-pre containers
-
-  */
-  function fixMarkup(value) {
-       if (options.tabReplace) {
-         value = value.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1, offset, s) {
-           return p1.replace(/\t/g, options.tabReplace);
-         });
-       }
-       if (options.useBR) {
-         value = value.replace(/\n/g, '<br>');
-       }
-       return value;
-  }
-
-  /*
-  Applies highlighting to a DOM node containing code. Accepts a DOM node and
-  two optional parameters for fixMarkup.
-  */
-  function highlightBlock(block) {
-       var text = options.useBR ? block.innerHTML
-         .replace(/\n/g,'').replace(/<br>|<br [^>]*>/g, '\n').replace(/<[^>]*>/g,'')
-         : block.textContent;
-       var language = blockLanguage(block);
-       if (language == 'no-highlight')
-           return;
-       var result = language ? highlight(language, text, true) : highlightAuto(text);
-       var original = nodeStream(block);
-       if (original.length) {
-         var pre = document.createElementNS('http://www.w3.org/1999/xhtml', 'pre');
-         pre.innerHTML = result.value;
-         result.value = mergeStreams(original, nodeStream(pre), text);
-       }
-       result.value = fixMarkup(result.value);
-
-       block.innerHTML = result.value;
-       block.className += ' hljs ' + (!language && result.language || '');
-       block.result = {
-         language: result.language,
-         re: result.relevance
-       };
-       if (result.second_best) {
-         block.second_best = {
-           language: result.second_best.language,
-           re: result.second_best.relevance
-         };
-       }
-  }
-
-  var options = {
-       classPrefix: 'hljs-',
-       tabReplace: null,
-       useBR: false,
-       languages: undefined
-  };
-
-  /*
-  Updates highlight.js global options with values passed in the form of an object
-  */
-  function configure(user_options) {
-       options = inherit(options, user_options);
-  }
-
-  /*
-  Applies highlighting to all <pre><code>..</code></pre> blocks on a page.
-  */
-  function initHighlighting() {
-       if (initHighlighting.called)
-         return;
-       initHighlighting.called = true;
-
-       var blocks = document.querySelectorAll('pre code');
-       Array.prototype.forEach.call(blocks, highlightBlock);
-  }
-
-  /*
-  Attaches highlighting to the page load event.
-  */
-  function initHighlightingOnLoad() {
-       addEventListener('DOMContentLoaded', initHighlighting, false);
-       addEventListener('load', initHighlighting, false);
-  }
-
-  var languages = {};
-  var aliases = {};
-
-  function registerLanguage(name, language) {
-       var lang = languages[name] = language(this);
-       if (lang.aliases) {
-         lang.aliases.forEach(function(alias) {aliases[alias] = name;});
-       }
-  }
-
-  function listLanguages() {
-       return Object.keys(languages);
-  }
-
-  function getLanguage(name) {
-       return languages[name] || languages[aliases[name]];
-  }
-
-  /* Interface definition */
-
-  this.highlight = highlight;
-  this.highlightAuto = highlightAuto;
-  this.fixMarkup = fixMarkup;
-  this.highlightBlock = highlightBlock;
-  this.configure = configure;
-  this.initHighlighting = initHighlighting;
-  this.initHighlightingOnLoad = initHighlightingOnLoad;
-  this.registerLanguage = registerLanguage;
-  this.listLanguages = listLanguages;
-  this.getLanguage = getLanguage;
-  this.inherit = inherit;
-
-  // Common regexps
-  this.IDENT_RE = '[a-zA-Z][a-zA-Z0-9_]*';
-  this.UNDERSCORE_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*';
-  this.NUMBER_RE = '\\b\\d+(\\.\\d+)?';
-  this.C_NUMBER_RE = '(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
-  this.BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
-  this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
-
-  // Common modes
-  this.BACKSLASH_ESCAPE = {
-       begin: '\\\\[\\s\\S]', relevance: 0
-  };
-  this.APOS_STRING_MODE = {
-       className: 'string',
-       begin: '\'', end: '\'',
-       illegal: '\\n',
-       contains: [this.BACKSLASH_ESCAPE]
-  };
-  this.QUOTE_STRING_MODE = {
-       className: 'string',
-       begin: '"', end: '"',
-       illegal: '\\n',
-       contains: [this.BACKSLASH_ESCAPE]
-  };
-  this.PHRASAL_WORDS_MODE = {
-       begin: /\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/
-  };
-  this.C_LINE_COMMENT_MODE = {
-       className: 'comment',
-       begin: '//', end: '$',
-       contains: [this.PHRASAL_WORDS_MODE]
-  };
-  this.C_BLOCK_COMMENT_MODE = {
-       className: 'comment',
-       begin: '/\\*', end: '\\*/',
-       contains: [this.PHRASAL_WORDS_MODE]
-  };
-  this.HASH_COMMENT_MODE = {
-       className: 'comment',
-       begin: '#', end: '$',
-       contains: [this.PHRASAL_WORDS_MODE]
-  };
-  this.NUMBER_MODE = {
-       className: 'number',
-       begin: this.NUMBER_RE,
-       relevance: 0
-  };
-  this.C_NUMBER_MODE = {
-       className: 'number',
-       begin: this.C_NUMBER_RE,
-       relevance: 0
-  };
-  this.BINARY_NUMBER_MODE = {
-       className: 'number',
-       begin: this.BINARY_NUMBER_RE,
-       relevance: 0
-  };
-  this.CSS_NUMBER_MODE = {
-       className: 'number',
-       begin: this.NUMBER_RE + '(' +
-         '%|em|ex|ch|rem'  +
-         '|vw|vh|vmin|vmax' +
-         '|cm|mm|in|pt|pc|px' +
-         '|deg|grad|rad|turn' +
-         '|s|ms' +
-         '|Hz|kHz' +
-         '|dpi|dpcm|dppx' +
-         ')?',
-       relevance: 0
-  };
-  this.REGEXP_MODE = {
-       className: 'regexp',
-       begin: /\//, end: /\/[gim]*/,
-       illegal: /\n/,
-       contains: [
-         this.BACKSLASH_ESCAPE,
-         {
-           begin: /\[/, end: /\]/,
-           relevance: 0,
-           contains: [this.BACKSLASH_ESCAPE]
-         }
-       ]
-  };
-  this.TITLE_MODE = {
-       className: 'title',
-       begin: this.IDENT_RE,
-       relevance: 0
-  };
-  this.UNDERSCORE_TITLE_MODE = {
-       className: 'title',
-       begin: this.UNDERSCORE_IDENT_RE,
-       relevance: 0
-  };
-};
diff --git a/share/nitdoc/js/lib/nit.js b/share/nitdoc/js/lib/nit.js
deleted file mode 100644 (file)
index 1b4aff3..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/* 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.
-
-   Documentation generator for the nit language.
-   Generate API documentation in HTML format from nit source code.
-*/
-
-hljs.registerLanguage('nit', function(hljs) {
-       var METHOD_RE = '[a-z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
-       var KEYWORDS = {
-               keyword: 'abort abstract and as assert break class continue do else end enum extern for fun ' +
-               'if import in init interface intern intrude is isa isset label loop module new nullable not ' +
-               'once or protected private redef return self super then type universal var ' +
-               'when while writable',
-               literal: "true false null"
-       };
-       var COMMENT = {
-               className: 'comment',
-               begin: '#', end: '$',
-       };
-       var SUBST = {
-               className: 'subst',
-               begin: '{', end: '}',
-               keywords: KEYWORDS
-       };
-       var STRING = {
-               className: 'string',
-               contains: [hljs.BACKSLASH_ESCAPE, SUBST],
-               variants: [
-                       {begin: /"/, end: /"/},
-               ]
-       };
-       var CHAR = {
-               className: 'char',
-               contains: [hljs.BACKSLASH_ESCAPE, SUBST],
-               begin: /'/, end: /'/,
-       };
-       var TYPE = {
-               className: 'type',
-               begin: '[A-Z]\\w*'
-       }
-       var PARAMS = {
-               className: 'params',
-               begin: '\\(', end: '\\)',
-               keywords: KEYWORDS,
-               contains: [TYPE]
-       };
-       var RET_TYPE = {
-               className: 'rettype',
-               begin: ':', end: '$|do|is|=',
-               keywords: 'nullable',
-               returnEnd: true,
-               contains: [TYPE]
-       }
-       var DO_BLOCK = {
-               className: 'block',
-               begin: 'do', end: '$|end',
-               keywords: KEYWORDS
-       }
-       var IS_BLOCK = {
-               className: 'modifiers',
-               begin: 'is', end: '$',
-               keywords: KEYWORDS
-       }
-       var CONTAINS = [
-               STRING,
-               CHAR,
-               COMMENT,
-               TYPE,
-               {
-                       className: 'module',
-                       beginKeywords: 'module', end: '$',
-                       contains: [
-                               hljs.inherit(hljs.TITLE_MODE, {begin: '[a-z_]\\w*'}),
-                               COMMENT
-                       ]
-               },
-               {
-                       className: 'import',
-                       begin: '(intrude )?import', end: '$',
-                       keywords: 'intrude import',
-                       contains: [
-                               {
-                                       className: 'module',
-                                       begin: '[a-z_]\\w*'
-                               },
-                               COMMENT
-                       ]
-               },
-               {
-                       className: 'class',
-                       begin: '(redef |private |protected )?(abstract )?(class|interface)', end: '$',
-                       keywords: 'redef private protected abstract class interface',
-                       contains: [
-                               hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Z]\\w*'}),
-                               {
-                                       className: 'super',
-                                       begin: '\\bsuper', end: '$',
-                                       keywords: 'super',
-                                       contains: [TYPE]
-                               },
-                               COMMENT
-                       ]
-               },
-               {
-                       className: 'fun',
-                       begin: '(redef |private |protected )?(fun|init|type)\\b', end: '$',
-                       keywords: KEYWORDS,
-                       contains: [
-                               PARAMS,
-                               RET_TYPE,
-                               DO_BLOCK,
-                               IS_BLOCK,
-                               {
-                                       className: 'title',
-                                       begin: '\\b[a-zA-Z_][a-zA-Z_]*\\b'
-                               },
-                               COMMENT
-                       ]
-               },
-               {
-                       className: 'number',
-                       begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
-                       relevance: 0
-               }
-       ];
-       SUBST.contains = CONTAINS;
-
-       return {
-               keywords: KEYWORDS,
-               contains: CONTAINS
-       };
-});
diff --git a/share/nitdoc/js/lib/utils.js b/share/nitdoc/js/lib/utils.js
deleted file mode 100644 (file)
index 26304d8..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* 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.
-
-   Documentation generator for the nit language.
-   Generate API documentation in HTML format from nit source code.
-*/
-
-/*
- * Utils module
- */
-String.prototype.startsWith = function(prefix, caseSensitive) {
-       if(caseSensitive) {
-               return this.toUpperCase().indexOf(prefix.toUpperCase()) === 0;
-       }
-       return this.indexOf(prefix) === 0;
-}
-
-// Compare two strings using Sorensen-Dice Coefficient
-// see: http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
-String.prototype.dice = function(other) {
-       var length1 = this.length - 1;
-       var length2 = other.length - 1;
-       if(length1 < 1 || length2 < 1) return 0;
-
-       var bigrams2 = [];
-       for(var i = 0; i < length2; i++) {
-               bigrams2.push(other.substr(i, 2));
-       }
-
-       var intersection = 0;
-       for(var i = 0; i < length1; i++) {
-               var bigram1 = this.substr(i, 2);
-               for(var j = 0; j < length2; j++) {
-                       if(bigram1 == bigrams2[j]) {
-                               intersection++;
-                               bigrams2[j] = null;
-                               break;
-                       }
-               }
-       }
-       return (2.0 * intersection) / (length1 + length2);
-}
-
-/* base64 */
-
-String.prototype._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
-// public method for encoding
-String.prototype.base64Encode = function () {
-       var output = "";
-       var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
-       var i = 0;
-
-       input = this._utf8_encode();
-
-       while (i < input.length) {
-
-               chr1 = input.charCodeAt(i++);
-               chr2 = input.charCodeAt(i++);
-               chr3 = input.charCodeAt(i++);
-
-               enc1 = chr1 >> 2;
-               enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-               enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-               enc4 = chr3 & 63;
-
-               if (isNaN(chr2)) {
-                       enc3 = enc4 = 64;
-               } else if (isNaN(chr3)) {
-                       enc4 = 64;
-               }
-
-               output = output +
-               this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
-               this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
-
-       }
-       return output;
-};
-
-// public method for decoding
-String.prototype.base64Decode = function () {
-       var output = "";
-       var chr1, chr2, chr3;
-       var enc1, enc2, enc3, enc4;
-       var i = 0;
-
-       input = this.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-       while (i < input.length) {
-
-               enc1 = this._keyStr.indexOf(input.charAt(i++));
-               enc2 = this._keyStr.indexOf(input.charAt(i++));
-               enc3 = this._keyStr.indexOf(input.charAt(i++));
-               enc4 = this._keyStr.indexOf(input.charAt(i++));
-
-               chr1 = (enc1 << 2) | (enc2 >> 4);
-               chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-               chr3 = ((enc3 & 3) << 6) | enc4;
-
-               output = output + String.fromCharCode(chr1);
-
-               if (enc3 != 64) {
-                       output = output + String.fromCharCode(chr2);
-               }
-               if (enc4 != 64) {
-                       output = output + String.fromCharCode(chr3);
-               }
-
-       }
-       return output._utf8_decode();;
-};
-
-// private method for UTF-8 encoding
-String.prototype._utf8_encode = function () {
-       string = this.replace(/\r\n/g,"\n");
-       var utftext = "";
-
-       for (var n = 0; n < string.length; n++) {
-
-               var c = string.charCodeAt(n);
-
-               if (c < 128) {
-                       utftext += String.fromCharCode(c);
-               }
-               else if((c > 127) && (c < 2048)) {
-                       utftext += String.fromCharCode((c >> 6) | 192);
-                       utftext += String.fromCharCode((c & 63) | 128);
-               }
-               else {
-                       utftext += String.fromCharCode((c >> 12) | 224);
-                       utftext += String.fromCharCode(((c >> 6) & 63) | 128);
-                       utftext += String.fromCharCode((c & 63) | 128);
-               }
-
-       }
-       return utftext;
-};
-
-// private method for UTF-8 decoding
-String.prototype._utf8_decode = function () {
-       var string = "";
-       var i = 0;
-       var c = c1 = c2 = 0;
-
-       while ( i < this.length ) {
-
-               c = this.charCodeAt(i);
-
-               if (c < 128) {
-                       string += String.fromCharCode(c);
-                       i++;
-               }
-               else if((c > 191) && (c < 224)) {
-                       c2 = this.charCodeAt(i+1);
-                       string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
-                       i += 2;
-               }
-               else {
-                       c2 = this.charCodeAt(i+1);
-                       c3 = this.charCodeAt(i+2);
-                       string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
-                       i += 3;
-               }
-
-       }
-       return string;
-};
-
-// JQuery Case Insensitive :icontains selector
-$.expr[':'].icontains = function(obj, index, meta, stack){
-       return (obj.textContent.replace(/\[[0-9]+\]/g, "") || obj.innerText.replace(/\[[0-9]+\]/g, "") || jQuery(obj).text().replace(/\[[0-9]+\]/g, "") || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;
-};
-
-var Utils = {
-       // Extract anchor part (after #) from URL string
-       extractAnchor: function(url) {
-               var index = url.indexOf("#");
-               if (index >= 0) {
-                       return url.substring(index + 1);
-               }
-               return null;
-       },
-
-       delayEvent: function(handler, event) {
-               if(this.delayEvent.timeout) {
-                       clearTimeout(this.delayEvent.timeout);
-               }
-               this.delayEvent.timeout = setTimeout(function() {
-                   handler.call(event);
-               }, 50);
-       }
-};
diff --git a/share/nitdoc/js/nitdoc.quicksearch.js b/share/nitdoc/js/nitdoc.quicksearch.js
new file mode 100644 (file)
index 0000000..746d2e6
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ */
+
+/* Nitdoc QuickSearch widget */
+
+$.widget("nitdoc.quicksearch", {
+
+       options: {
+               list: {}, // List of raw results generated by nitdoc tool
+               fieldAttrs: {
+                       autocomplete: "off",
+               },
+               maxSize: 10
+       },
+
+       _create: function() {
+               // set widget options
+               this.element.attr(this.options.fieldAttrs);
+               // event dispatch
+               this._on(this.element, {
+                       "keydown": this._doKeyDown,
+                       "keyup": this._doKeyUp,
+                       "input": this._doInput
+               });
+               // add result table element once
+               this._popup = $("<div/>")
+                       .attr("id", "nitdoc-qs-popup")
+                       .css("position", "absolute")
+                       .css("z-index", 10000)
+                       .hide();
+               $("body").append(this._popup);
+               // make table disappear when a click occurs outside
+               $(document).click($.proxy(this.close, this));
+               this._autosizeTable();
+       },
+
+       /* events */
+
+       _doKeyDown: function(event) {
+               switch(event.keyCode) {
+                       case 38: // Up
+                               this._selectPrev();
+                               return false;
+                       case 40: // Down
+                               this._selectNext();
+                               return false;
+                       default:
+                               return true;
+                }
+       },
+
+       _doKeyUp: function(event) {
+               switch(event.keyCode) {
+                       case 38: // Up
+                       case 40: // Down
+                               break;
+                       case 13: // Enter
+                               this._loadResult();
+                               return false;
+                       case 27: // Escape
+                               this.element.blur();
+                               this.close();
+                               return true;
+                       default: // Other keys
+                               return true;
+               }
+       },
+
+       _doInput: function(event) {
+               Utils.delayEvent($.proxy(this.search, this));
+       },
+
+       /* Result lookup */
+
+       _getResults: function(query) {
+               var results = [];
+
+               // Prefix matches
+               var prefix_matches = [];
+               for(var entry in this.options.list) {
+                       if(!entry.startsWith(query, true)) {
+                               continue;
+                       }
+                       var cat = {
+                               name: entry,
+                               entries: this.options.list[entry]
+                       };
+                       prefix_matches.push(cat);
+
+                       if(entry == query) {
+                               cat.rank = 10;
+                       } else if(entry.toUpperCase() == query.toUpperCase()) {
+                               cat.rank = 5;
+                       } else if(entry[0] == query[0]) {
+                               cat.rank = 1.1 + query.dice(entry);
+                       } else {
+                               cat.rank = 1 + query.dice(entry);
+                       }
+               }
+               if(prefix_matches.length > 0) {
+                       prefix_matches.sort(this._rankSorter);
+                       for(var i in prefix_matches) {
+                               var cat = prefix_matches[i];
+                               for(var j in cat.entries) {
+                                       var entry = cat.entries[j];
+                                       entry.name = cat.name;
+                                       results.push(entry);
+                               }
+                       }
+                       return results;
+               }
+
+               // Partial matches
+               var partial_matches = [];
+               for(var entry in this.options.list) {
+                       var cat = {
+                               name: entry,
+                               entries: this.options.list[entry]
+                       }
+                       cat.rank = query.dice(entry);
+                       if(cat.rank > 0) {
+                               partial_matches.push(cat);
+                       }
+               }
+               if(partial_matches.length > 0) {
+                       partial_matches.sort(this._rankSorter);
+                       for(var i in partial_matches) {
+                               var cat = partial_matches[i];
+                               for(var j in cat.entries) {
+                                       var entry = cat.entries[j];
+                                       entry.name = cat.name;
+                                       results.push(entry);
+                               }
+                       }
+               }
+
+               return results;
+       },
+
+       _rankSorter: function(a, b){
+               if(a.rank < b.rank) {
+                       return 1;
+               } else if(a.rank > b.rank) {
+                       return -1;
+               }
+               return 0;
+       },
+
+       /* Results table */
+
+       search: function() {
+               var query = this.element.val();
+               if(query) {
+                       var results = this._getResults(query);
+                       this.open(query, results);
+               }
+       },
+
+       open: function(query, results) {
+               this._popup.empty();
+               this._cards = [];
+               this._index = -1;
+
+               if(results.length == 0) {
+                       this.addNoResultCard();
+               }
+
+               if(results.length >= this.options.maxSize) {
+                       this.addOverflowUp(false);
+               }
+
+               for(var i in results) {
+                       var result = results[i];
+                       this.addCard(result.name, result.txt, result.url, this.options.rowCatClass)
+               }
+
+               if(results.length >= this.options.maxSize) {
+                       this.addOverflowDown(true);
+               }
+
+               if(results.length > 0) {
+                       this._setIndex(0);
+               }
+
+               this._popup.show();
+               this._autosizeTable();
+       },
+
+       close: function(target) {
+               if(target != this.element && target != this._popup) {
+                       this._popup.hide();
+               }
+       },
+
+       addCard: function(name, txt, url, cls) {
+               var card = $("<div/>")
+                       .addClass("qs-card")
+                       .addClass("qs-result")
+                       .data("searchDetails", {name: name, url: url})
+                       .data("index", this._cards.length)
+                       .append(
+                               $("<h1/>")
+                               .html(name)
+                               .addClass(cls)
+                       )
+                       .append(
+                               $("<span/>")
+                               .html(txt)
+                               .addClass("qs-info")
+                       )
+                       .mouseover($.proxy(this._mouseOverRow, this))
+                       .click($.proxy(this._clickRow, this))
+               this._cards.push(card);
+               if(this._cards.length >= this.options.maxSize) {
+                       card.hide();
+               }
+               this._popup.append(card);
+       },
+
+       addOverflowUp: function(active) {
+               this._popup.append(
+                       $("<div/>")
+                       .addClass("qs-overflow")
+                       .addClass("qs-overflow-up")
+                       .addClass(active ? "qs-overflow-active": "")
+                       .html("&#x25B2;")
+                       .click($.proxy(this._clickPrev, this))
+               );
+       },
+
+       addOverflowDown: function(active) {
+               this._popup.append(
+                       $("<div/>")
+                       .addClass("qs-overflow")
+                       .addClass("qs-overflow-down")
+                       .addClass(active ? "qs-overflow-active": "")
+                       .html("&#x25BC;")
+                       .click($.proxy(this._clickNext, this))
+               );
+       },
+
+       addNoResultCard: function() {
+               var card = $("<div/>")
+                       .addClass("qs-card qs-noresult")
+                       .html("Sorry, there is no match...");
+               this._popup.append(card);
+       },
+
+       _autosizeTable: function() {
+               this._popup.position({
+                       my: "left top",
+                       at: "left bottom",
+                       of: this.element
+               });
+               this._popup
+                       .css("min-width", this.element.outerWidth())
+                       .css("max-width", this.element.outerWidth());
+       },
+
+       _hasIndex: function(index) {
+               return index >= 0 && index < this._cards.length;
+       },
+
+       _hasPrev: function(index) {
+               return index - 1 >= 0;
+       },
+
+       _hasNext: function(index) {
+               return index + 1 < this._cards.length;
+       },
+
+       _setIndex: function(index) {
+               if(this._hasIndex(this._index)) {
+                       this._cards[this._index].removeClass("qs-active");
+               }
+               this._index = index;
+               if(this._hasIndex(this._index)) {
+                       this._cards[this._index].addClass("qs-active");
+               }
+       },
+
+       _selectPrev: function() {
+               if(this._hasPrev(this._index)) {
+                       this._setIndex(this._index - 1);
+                       if(!this._cards[this._index].is(":visible")) {
+                               this._popup.find(".qs-result:visible").last().hide();
+                               this._popup.find(".qs-overflow-down").addClass("qs-overflow-active");
+                               this._cards[this._index].show();
+                               if(!this._hasPrev(this._index)) {
+                                       this._popup.find(".qs-overflow-up").removeClass("qs-overflow-active");
+                               }
+                       }
+               } else {
+               }
+       },
+
+       _selectNext: function() {
+               if(this._hasNext(this._index)) {
+                       this._setIndex(this._index + 1);
+                       if(!this._cards[this._index].is(":visible")) {
+                               this._popup.find(".qs-result:visible").first().hide();
+                               this._popup.find(".qs-overflow-up").addClass("qs-overflow-active");
+                               this._cards[this._index].show();
+                               if(!this._hasNext(this._index)) {
+                                       this._popup.find(".qs-overflow-down").removeClass("qs-overflow-active");
+                               }
+                       }
+               }
+       },
+
+       // Load selected search result page
+       _loadResult: function() {
+               if(this._index > -1) {
+                       window.location = this._cards[this._index].data("searchDetails").url;
+                       return;
+               }
+               if(this.element.val().length == 0) { return; }
+
+               window.location = this.options.gotoPage + "#q=" + this.element.val();
+               if(window.location.href.indexOf(this.options.gotoPage) > -1) {
+                       location.reload();
+               }
+       },
+
+       /* table events */
+
+       _clickNext: function(event) {
+               event.stopPropagation();
+               this._selectNext();
+       },
+
+       _clickPrev: function(event) {
+               event.stopPropagation();
+               this._selectPrev();
+       },
+
+       _clickRow: function(event) {
+               window.location = $(event.currentTarget).data("searchDetails")["url"];
+       },
+
+       _mouseOverRow: function(event) {
+               this._setIndex($(event.currentTarget).data("index"));
+       }
+});
+
+var searchField = $("<input/>")
+.addClass("form-control search-input")
+.attr({
+       id: "nitdoc-qs-field",
+       type: "text",
+       placeholder: "Search..."
+})
+
+$("#search-placeholder").append(
+       $("<form>")
+       .addClass("navbar-form navbar-right")
+       .on("submit", function() { return false; })
+       .css("margin-bottom", 0)
+       .css("margin-top", 0)
+       .append(
+               $("<div>")
+               .addClass("form-group has-icon")
+               .append(searchField)
+               .append(
+                       $("<span>")
+                       .addClass("glyphicon glyphicon-search form-control-icon text-muted")
+               )
+       )
+);
+
+searchField.quicksearch({
+       list: this.nitdocQuickSearchRawList
+});
diff --git a/share/nitdoc/js/nitdoc.utils.js b/share/nitdoc/js/nitdoc.utils.js
new file mode 100644 (file)
index 0000000..ac19c29
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+/* Utils module */
+
+String.prototype.startsWith = function(prefix, caseSensitive) {
+       if(caseSensitive) {
+               return this.toUpperCase().indexOf(prefix.toUpperCase()) === 0;
+       }
+       return this.indexOf(prefix) === 0;
+}
+
+// Compare two strings using Sorensen-Dice Coefficient
+// see: http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
+String.prototype.dice = function(other) {
+       var length1 = this.length - 1;
+       var length2 = other.length - 1;
+       if(length1 < 1 || length2 < 1) return 0;
+
+       var bigrams2 = [];
+       for(var i = 0; i < length2; i++) {
+               bigrams2.push(other.substr(i, 2));
+       }
+
+       var intersection = 0;
+       for(var i = 0; i < length1; i++) {
+               var bigram1 = this.substr(i, 2);
+               for(var j = 0; j < length2; j++) {
+                       if(bigram1 == bigrams2[j]) {
+                               intersection++;
+                               bigrams2[j] = null;
+                               break;
+                       }
+               }
+       }
+       return (2.0 * intersection) / (length1 + length2);
+}
+
+var Utils = {
+       delayEvent: function(handler, event) {
+               if(this.delayEvent.timeout) {
+                       clearTimeout(this.delayEvent.timeout);
+               }
+               this.delayEvent.timeout = setTimeout(function() {
+                   handler.call(event);
+               }, 100);
+       },
+
+       scrollTo: function(target) {
+               var element = $(target);
+               if(element[0]) {
+                       $("body, html").animate({
+                               scrollTop: element.offset().top - 60
+                       });
+               }
+       },
+
+       openTab: function(e) {
+               // Open tab
+               var url = document.location.toString();
+               if (url.match('#')) {
+                       var hash = url.split('#')[1];
+                       var element = $('.nav-tabs a[href="#' + hash + '"]');
+                       if(element[0]) {
+                               element.tab('show');
+                       } else {
+                               Utils.scrollTo('#' + hash);
+                       }
+               }
+
+               // Jump to id
+               var obj = new URL(url);
+               var arg = obj.searchParams.get("def");
+               if(arg) {
+                       var def = '#' + arg;
+                       $('.card.active').removeClass('active');
+                       $(def).addClass('active');
+                       $(def).find('.collapse').collapse();
+                       Utils.scrollTo(def);
+               }
+       }
+};
+
+Utils.openTab();
+
+window.addEventListener("hashchange", Utils.openTab, false);
+
+// Scroll on hash click
+$('.summary a[href*=#]').on('click', function(e) {
+       e.preventDefault();
+       Utils.scrollTo(e.currentTarget.hash);
+       history.pushState({}, '', e.currentTarget.hash);
+});
+
+// Change hash for page-reload
+$('.nav-tabs a[href]').on('shown.bs.tab', function (e) {
+       history.pushState({}, '', e.target.hash)
+});
diff --git a/share/nitdoc/js/plugins/filtering.js b/share/nitdoc/js/plugins/filtering.js
deleted file mode 100644 (file)
index fa0f12e..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* 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.
-
-   Documentation generator for the nit language.
-   Generate API documentation in HTML format from nit source code.
-*/
-
-/*
- * Nitdoc Filtering
- *
- * Allow user to filter sidebar entries and search page
- */
-var Filtering = {
-
-       // Allow user to filter sidebar box entries by name
-       enableSidebarTextFilters: function(filterSelector) {
-               var div = $(document.createElement("div"))
-               .addClass("nitdoc-ui-filter")
-               .append(
-                       $(document.createElement("input"))
-                       .addClass("nitdoc-ui-filter-field")
-                       .addClass("nitdoc-ui-filter-field-notused")
-                       .attr("type", "text")
-                       .attr("value",  "filter...")
-                       .keyup(function() {
-                               var box = $(this).parents("nav.filterable");
-                               var value = $(this).val();
-                               box.find("ul li:not(:icontains('" + value + "'))").hide();
-                               box.find("ul li:icontains('" + value + "')").show();
-                       })
-                       .focusout(function() {
-                               if($(this).val() == "") {
-                                       $(this).addClass("nitdoc-ui-filter-field-notused");
-                                       $(this).val("filter...");
-                               }
-                       })
-                       .focusin(function() {
-                               if($(this).val() == "filter...") {
-                                       $(this).removeClass("nitdoc-ui-filter-field-notused");
-                                       $(this).val("");
-                               }
-                       })
-               );
-               $(filterSelector).after(div);
-               this.preloadSidebarTextFilters();
-       },
-
-       // Prealod filters using search query
-       preloadSidebarTextFilters: function() {
-               var anchor = Utils.extractAnchor(document.location.hash);
-               if(!anchor || anchor.indexOf("q=") == -1) return;
-
-               var query = anchor.substring(2);
-               if(!query) return;
-
-               $(".nitdoc-ui-filter input:text")
-               .val(query)
-               .removeClass("nitdoc-ui-notused")
-               .trigger("keyup");
-       },
-
-       // Allow user to filter side bar box entries by Introduced/Refined/inHerited type
-       enableSidebarTypeFilters: function(filterSelector) {
-               var box = $(filterSelector);
-               var types = {};
-
-               box.find("li").each(function() {
-                       var span = $(this).find("span:first");
-                       if(!types[span.html()]) types[span.html()] = {
-                               title: span.attr("title"),
-                               class: $(this).attr("class")
-                       }
-               });
-
-               for(var type in types) {
-                       var a = $(document.createElement("a"))
-                       .addClass("nitdoc-ui-filter-link")
-                       .html(type)
-                       .attr("title", "Hide " + types[type].title)
-                       .attr("data-filter-class", types[type].class)
-                       .toggle(
-                               function() {
-                                       var hclass = $(this).attr("data-filter-class");
-                                       $(this).parents(filterSelector).find("li." + hclass).hide();
-                                       $(this).addClass("nitdoc-ui-filter-hidden")
-                               },
-                               function() {
-                                       var hclass = $(this).attr("data-filter-class");
-                                       $(this).parents(filterSelector).find("li." + hclass).show();
-                                       $(this).removeClass("nitdoc-ui-filter-hidden")
-                               }
-                       )
-                       $(filterSelector).find(".nitdoc-ui-filter").append(a);
-               }
-       },
-
-       // Allow user to filter sidebar box entries by name
-       enableSearchPageField: function(filterSelector) {
-               var div = $(document.createElement("div"))
-               .addClass("nitdoc-ui-searchpage-filter")
-               .append(
-                       $(document.createElement("input"))
-                       .addClass("nitdoc-ui-searchpage-field")
-                       .addClass("nitdoc-ui-filter-field-notused")
-                       .attr("type", "text")
-                       .attr("value",  "filter...")
-                       .keyup(function() {
-                               var box = $(this).parents(".content.fullpage").find("article.filterable");
-                               var value = $(this).val();
-                               box.find("ul li:not(:icontains('" + value + "'))").hide();
-                               box.find("ul li:icontains('" + value + "')").show();
-                       })
-                       .focusout(function() {
-                               if($(this).val() == "") {
-                                       $(this).addClass("nitdoc-ui-filter-field-notused");
-                                       $(this).val("filter...");
-                               }
-                       })
-                       .focusin(function() {
-                               if($(this).val() == "filter...") {
-                                       $(this).removeClass("nitdoc-ui-filter-field-notused");
-                                       $(this).val("");
-                               }
-                       })
-               );
-               $(filterSelector).after(div);
-               this.preloadSearchPageField();
-       },
-
-       // Prealod filter using search query
-       preloadSearchPageField: function() {
-               var anchor = Utils.extractAnchor(document.location.hash);
-               if(!anchor || anchor.indexOf("q=") == -1) return;
-
-               var query = anchor.substring(2);
-               if(!query) return;
-
-               $(".nitdoc-ui-searchpage-field")
-               .val(query)
-               .removeClass("nitdoc-ui-notused")
-               .trigger("keyup");
-       }
-};
-
-Filtering.enableSidebarTextFilters("nav.filterable h3");
-Filtering.enableSidebarTypeFilters("nav.filterable");
-Filtering.enableSearchPageField(".content.fullpage h1:contains('Search')");
diff --git a/share/nitdoc/js/plugins/github.js b/share/nitdoc/js/plugins/github.js
deleted file mode 100644 (file)
index c77c0d0..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/*\r
- * Nitdoc.Github comment edition module\r
- *\r
- * Allows user to modify source code comments directly from the Nitdoc\r
- */\r
-define([\r
-       "jquery",\r
-       "github-api",\r
-       "highlight",\r
-       "marked",\r
-       "nit",\r
-       "plugins/modalbox",\r
-       "plugins/github/loginbox",\r
-       "plugins/github/commentbox",\r
-       "utils"\r
-], function($, GithubAPI, hljs, marked) {\r
-       var GithubUser = function(login, password, repo, branch) {\r
-               this.login = login;\r
-               this.password = password;\r
-               this.repo = repo;\r
-               this.auth = "Basic " +  (login + ':' + password).base64Encode();\r
-               this.branch = branch;\r
-       }\r
-\r
-       var GithubUI = {\r
-               init: function(upstream, basesha1) {\r
-                       console.info("Github plugin: init GitHub module (upstream: "+ upstream +", base: " + basesha1 + ")");\r
-                       this.origin = this._parseUpstream(upstream);\r
-                       this._initMarked();\r
-                       // Add github menu\r
-                       $("#topmenu>.container-fluid").append(\r
-                               $("<a/>")\r
-                               .attr({\r
-                                       "id": "nitdoc-github-li",\r
-                                       "type": "button",\r
-                                       "class": "navbar-btn navbar-right btn-link",\r
-                                       "href": "#",\r
-                                       "data-container": "body",\r
-                                       "data-toggle": "popover",\r
-                                       "data-placement": "bottom",\r
-                                       "data-content": "bottom",\r
-                                       "data-html": "true",\r
-                               })\r
-                               .loginbox()\r
-                               //.loginbox("displayLogin")\r
-                               .bind("loginbox_logoff", function() {\r
-                                       GithubUI.disactivate();\r
-                               })\r
-                               .bind("loginbox_login", function(event, infos) {\r
-                                       GithubUI._tryLoginFromCredentials(infos);\r
-                               })\r
-                       );\r
-                       // check local session\r
-                       this._tryLoginFromLocalSession();\r
-               },\r
-\r
-               activate: function(user, origin) {\r
-                       this.openedComments = 0;\r
-                       this._saveSession(user);\r
-                       $("#nitdoc-github-li").loginbox("displayLogout", origin, user);\r
-                       this._attachCommentBoxes();\r
-                       this._reloadComments();\r
-\r
-                       // Prevent page unload if there is comments in editing mode\r
-                       $(window).on('beforeunload', function() {\r
-                               if(GithubUI.openedComments > 0){\r
-                                       return "There is uncommited modified comments. Are you sure you want to leave this page?";\r
-                               }\r
-                       });\r
-               },\r
-\r
-               disactivate: function() {\r
-                       if(this.openedComments > 0){\r
-                               if(!confirm('There is uncommited modified comments. Are you sure you want to leave this page?')) {\r
-                                       return false;\r
-                               }\r
-                       }\r
-\r
-                       localStorage.clear();\r
-                       $("#nitdoc-github-li").loginbox("toggle");\r
-                       $("#nitdoc-github-li").loginbox("displayLogin");\r
-                       $(window).unbind('beforeunload');\r
-                       //window.location.reload();\r
-               },\r
-\r
-               /* login */\r
-\r
-               _checkLoginInfos: function(infos) {\r
-                       if(!infos.login || !infos.password || !infos.repo || !infos.branch) {\r
-                               $("<p/>")\r
-                               .text("Please enter your GitHub username, password, repository and branch.")\r
-                               .modalbox({\r
-                                       title: "Sign in error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       } else {\r
-                               return true;\r
-                       }\r
-               },\r
-\r
-               _tryLoginFromCredentials: function(infos) {\r
-                       if(this._checkLoginInfos(infos)) {\r
-                               var isok = this._tryLogin(infos.login, infos.password, infos.repo, infos.branch);\r
-                               if(isok === true) {\r
-                                       this.activate(this.user, this.origin);\r
-                               } else {\r
-                                       if(isok == "error:login") {\r
-                                               $("<p/>")\r
-                                               .text("The username, password, repo or branch you entered is incorrect.")\r
-                                               .modalbox({\r
-                                                       title: "Github sign in error",\r
-                                                       isError: true\r
-                                               })\r
-                                               .modalbox("open");\r
-                                       } else if(isok == "error:sha") {\r
-                                               $("<p/>")\r
-                                               .text("The provided Github repository must contain the base commit '" + this.origin.sha + "'.")\r
-                                               .modalbox({\r
-                                                       title: "Github base commit error",\r
-                                                       isError: true\r
-                                               })\r
-                                               .modalbox("open");\r
-                                       } else if(isok == "error:profile") {\r
-                                               $("<p/>")\r
-                                               .text("Please set your public name and email in your " +\r
-                                                       "<a href='https://github.com/settings/profile'>GitHub profile</a>." +\r
-                                                       "<br/><br/>Your public profile informations are used to sign-off your commits.")\r
-                                               .modalbox({\r
-                                                       title: "Github profile error",\r
-                                                       isError: true\r
-                                               })\r
-                                               .modalbox("open");\r
-                                       }\r
-                               }\r
-                       }\r
-               },\r
-\r
-               _tryLoginFromLocalSession: function() {\r
-                       if(localStorage.user) {\r
-                               var session = JSON.parse(localStorage.user);\r
-                               var isok = this._tryLogin(\r
-                                       session.login,\r
-                                       session.password.base64Decode(),\r
-                                       session.repo,\r
-                                       session.branch\r
-                               );\r
-                               if(isok === true) {\r
-                                       this.activate(this.user, this.origin);\r
-                               } else {\r
-                                       console.debug("Github plugin: Session found but authentification failed");\r
-                                       localStorage.clear();\r
-                               }\r
-                       } else {\r
-                               console.debug("Github plugin: No session found");\r
-                       }\r
-               },\r
-\r
-               _tryLogin: function(login, password, repo, branch) {\r
-                       var tmpUser = new GithubUser(login, password, repo, branch);\r
-                       if(!GithubAPI.login(tmpUser)) {\r
-                               return "error:login";\r
-                       }\r
-                       if(!tmpUser.infos.name || !tmpUser.infos.email) {\r
-                               return "error:profile";\r
-                       }\r
-                       var commit = GithubAPI.getCommit(tmpUser, this.origin.sha);\r
-                       if(!commit || !commit.sha) {\r
-                               return "error:sha";\r
-                       }\r
-                       this.user = tmpUser;\r
-                       return true;\r
-               },\r
-\r
-               _saveSession: function(user) {\r
-                       localStorage.user = JSON.stringify({\r
-                               login: user.login,\r
-                               password: user.password.base64Encode(),\r
-                               repo: user.repo,\r
-                               branch: user.branch,\r
-                       });\r
-                       // check local storage synchro with branch\r
-                       if(localStorage.base != this.origin.sha) {\r
-                               console.log("Base changed: cleaned cache");\r
-                               localStorage.requests = "[]";\r
-                               localStorage.base = this.origin.sha;\r
-                       }\r
-               },\r
-\r
-               /* html decoration */\r
-\r
-               // Attach edit button on each comment\r
-               _attachCommentBoxes: function() {\r
-                       $("textarea.baseComment").each(function() {\r
-                               $(this).commentbox();\r
-\r
-                               var isNew = false;\r
-                               if(!$(this).val()) {\r
-                                       isNew = true;\r
-                                       $(this).nextAll(".info:first").find(".noComment").hide()\r
-                                       $(this).nextAll(".info:first").before(\r
-                                               $("<div/>")\r
-                                               .hide()\r
-                                               .addClass("comment")\r
-                                               .append(\r
-                                                       $("<div/>").addClass("nitdoc")\r
-                                               )\r
-                                       )\r
-                               }\r
-\r
-                               $(this).nextAll(".info:first").prepend(\r
-                                       $("<a/>")\r
-                                       .addClass("nitdoc-github-editComment")\r
-                                       .css("cursor", "pointer")\r
-                                       .text((isNew ? "add" : "edit") + " comment")\r
-                                       .click($.proxy(GithubUI._openCommentBox, GithubUI, null, $(this)))\r
-                                       .after(" for ")\r
-                               )\r
-\r
-                               $(this).bind("commentbox_commit", function(event, data) {\r
-                                       GithubUI._saveChanges(data);\r
-                                       $(this).commentbox("close");\r
-                                       GithubUI._reloadComments();\r
-                               })\r
-                               .bind("commentbox_preview", function(event, data) {\r
-                                       $("<div/>")\r
-                                       .append($("<h4/>").text("Comment:"))\r
-                                       .append(\r
-                                               $("<div/>")\r
-                                               .addClass("description")\r
-                                               .append(\r
-                                                       $("<div/>")\r
-                                                       .addClass("comment")\r
-                                                       .append(\r
-                                                               $("<div/>")\r
-                                                               .addClass("nitdoc")\r
-                                                               .html(marked(data.value))\r
-                                                       )\r
-                                               )\r
-                                       )\r
-                                       .append($("<h4/>").text("Message:"))\r
-                                       .append(\r
-                                               $("<div/>")\r
-                                               .addClass("description")\r
-                                               .append(\r
-                                                       $("<div/>")\r
-                                                       .addClass("comment")\r
-                                                       .append(\r
-                                                               $("<div/>").html(marked(data.message))\r
-                                                       )\r
-                                               )\r
-                                       )\r
-                                       .modalbox({\r
-                                               title: "Preview comment",\r
-                                               css: {"min-width": "500px"}\r
-                                       })\r
-                                       .modalbox("open");\r
-                               })\r
-                               .bind("commentbox_open", function(event, data) {\r
-                                       GithubUI.openedComments++;\r
-                                       $(this).nextAll(".comment").hide();\r
-                               })\r
-                               .bind("commentbox_close", function(event, data) {\r
-                                       GithubUI.openedComments--;\r
-                                       $(this).nextAll(".comment").show();\r
-                               });\r
-                       });\r
-               },\r
-\r
-               // reload comments from saved pull request\r
-               _reloadComments: function() {\r
-                       if(!localStorage.requests){ return; }\r
-                       $("p.pullRequest").remove();\r
-                       var requests = JSON.parse(localStorage.requests);\r
-                       // Look for modified comments in page\r
-                       for(i in requests) {\r
-                               if(!requests[i]) { continue; }\r
-                               var request = requests[i];\r
-                               $("textarea[data-comment-location=\"" + request.location + "\"]").each(function () {\r
-                                       if(request.isClosed) {\r
-                                               var oldComment = request.oldComment.base64Decode();\r
-                                               var htmlComment = marked(oldComment);\r
-                                               $(this).val(oldComment);\r
-                                               if(!$(this).val()) {\r
-                                                       $(this).nextAll("div.comment:first").hide();\r
-                                               } else {\r
-                                                       $(this).nextAll("div.comment:first").show();\r
-                                               }\r
-                                               $(this).nextAll("div.comment").find("div.nitdoc").empty().html(htmlComment);\r
-                                               $(this).nextAll("p.info").find("a.nitdoc-github-editComment").show();\r
-                                       } else {\r
-                                               var newComment = request.comment.base64Decode();\r
-                                               var htmlComment = marked(newComment);\r
-                                               $(this).val(newComment);\r
-                                               if(!$(this).val()) {\r
-                                                       $(this).nextAll("div.comment:first").hide();\r
-                                               } else {\r
-                                                       $(this).nextAll("div.comment:first").show();\r
-                                               }\r
-                                               $(this).nextAll("div.comment").find("div.nitdoc").empty().html(htmlComment);\r
-                                               GithubUI._addPullRequestLink($(this), request);\r
-                                               $(this).nextAll("p.info").find("a.nitdoc-github-editComment").hide();\r
-                                       }\r
-                               });\r
-                       }\r
-               },\r
-\r
-               _addPullRequestLink: function(baseArea, request) {\r
-                       baseArea.nextAll("p.info").before(\r
-                               $("<p/>")\r
-                               .addClass("pullRequest inheritance")\r
-                               .text("comment modified in ")\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .attr({\r
-                                               href: request.request.html_url,\r
-                                               title: "Review on GitHub"\r
-                                       })\r
-                                       .text("pull request #" + request.request.number)\r
-                               )\r
-                               .append(" ")\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .data("pullrequest-number", request.request.number)\r
-                                       .addClass("nitdoc-github-update")\r
-                                       .text("update")\r
-                                       .click($.proxy(GithubUI._doUpdateRequest, GithubUI, null, baseArea, request))\r
-                               )\r
-                               .append(" ")\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .data("pullrequest-number", request.request.number)\r
-                                       .addClass("nitdoc-github-cancel")\r
-                                       .text("cancel")\r
-                                       .click($.proxy(GithubUI._doCancelRequest, GithubUI, null, baseArea, request))\r
-                               )\r
-                       );\r
-               },\r
-\r
-               /* github calls */\r
-\r
-               _saveChanges: function(edit) {\r
-                       // if pull request update close existing pull request for the comment\r
-                       if(edit.requestID) {\r
-                               this._closePullRequest(edit.requestID);\r
-                       }\r
-                       edit.oldContent = this._getFileContent(edit.location.path);\r
-                       edit.newContent = this._mergeComment(edit.oldContent, edit.newComment, edit.location);\r
-                       edit.request = this._pushChanges(edit)\r
-                       if(!edit.request) {\r
-                               $("<p/>")\r
-                               .text("Unable to commit changes.<br/>" + response)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return;\r
-                       }\r
-                       this._saveRequest(edit);\r
-               },\r
-\r
-               // save pull request in local storage\r
-               _saveRequest: function(edit) {\r
-                       var requests = {};\r
-                       if(localStorage.requests) {requests = JSON.parse(localStorage.requests)}\r
-                       requests[edit.request.number] = {\r
-                               request: edit.request,\r
-                               location: edit.location.origin,\r
-                               comment: edit.newComment.base64Encode(),\r
-                               oldComment: edit.oldComment.base64Encode()\r
-                       };\r
-                       localStorage.requests = JSON.stringify(requests);\r
-               },\r
-\r
-               /*\r
-                  Creating a new pull request with the new comment take 5 steps:\r
-                       1. get the base tree from latest commit\r
-\r
-                       2. create a new blob with updated file content\r
-                       3. post a new tree from base tree and blob\r
-                       4. post the new commit with new tree\r
-                       5. create the pull request\r
-               */\r
-               _pushChanges: function(edit) {\r
-                       var baseTree = GithubAPI.getTree(this.user, this.origin.sha);\r
-                       if(!baseTree.sha) {\r
-                               $("<p/>")\r
-                               .text("Unable to locate base tree.<br/>" + baseTree.status + ": " + baseTree.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       console.log("Base tree: " + baseTree.url);\r
-                       var newBlob = GithubAPI.createBlob(this.user, edit.newContent);\r
-                       if(!newBlob.sha) {\r
-                               $("<p/>")\r
-                               .text("Unable to create new blob.<br/>" + newBlob.status + ": " + newBlob.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       console.log("New blob: " + newBlob.url);\r
-                       var newTree = GithubAPI.createTree(this.user, baseTree, edit.location.path, newBlob);\r
-                       if(!newTree.sha) {\r
-                               $("<p/>")\r
-                               .text("Unable to create new tree.<br/>" + newTree.status + ": " + newTree.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       console.log("New tree: " + newTree.url);\r
-                       var newCommit = GithubAPI.createCommit(this.user, edit.message, baseTree.sha, newTree);\r
-                       if(!newCommit.sha) {\r
-                               $("<p/>")\r
-                               .text("Unable to create new commit.<br/>" + newCommit.status + ": " + newCommit.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       console.log("New commit: " + newCommit.url);\r
-                       var pullRequest = GithubAPI.createPullRequest(this.user, edit.title, "Pull request from Nitdoc", this.origin, newCommit.sha);\r
-                       if(!pullRequest.number) {\r
-                               $("<p/>")\r
-                               .text("Unable to create pull request.<br/>" + pullRequest.status + ": " + pullRequest.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       console.log("New pull request: " + pullRequest.url);\r
-                       return pullRequest;\r
-               },\r
-\r
-               // close previously opened pull request\r
-               _closePullRequest: function(number) {\r
-                       var requests = JSON.parse(localStorage.requests);\r
-                       if(!requests[number]) {\r
-                               $("<p/>")\r
-                               .text("Unable to close pull request.<br/>" + "Pull request " + number + "not found")\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       // close pull request\r
-                       var res = GithubAPI.updatePullRequest(this.user, "Closed from Nitdoc", "", "closed", requests[number].request);\r
-                       if(!res.id) {\r
-                               $("<p/>")\r
-                               .text("Unable to close pull request.<br/>" + res.status + ": " + res.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return false;\r
-                       }\r
-                       // update in localstorage\r
-                       requests[number].isClosed = true;\r
-                       localStorage.requests = JSON.stringify(requests);\r
-               },\r
-\r
-               /* internals */\r
-\r
-               _initMarked: function() {\r
-                       var renderer = new marked.Renderer();\r
-                       renderer.code = function(code) {\r
-                               return '<pre class="nitcode hljs">' + hljs.highlight('nit', code).value + '</pre>';\r
-                       }\r
-                       renderer.codespan = function(code) {\r
-                               return '<code class="nitcode hljs">' + hljs.highlight('nit', code).value + '</code>';\r
-                       }\r
-                       marked.setOptions({\r
-                               renderer: renderer,\r
-                               gfm: true,\r
-                               tables: true,\r
-                               breaks: true,\r
-                               pedantic: false,\r
-                               sanitize: true,\r
-                               smartLists: true,\r
-                               smartypants: false\r
-                       });\r
-               },\r
-\r
-               _parseUpstream: function(upstream) {\r
-                       var parts = upstream.split(":");\r
-                       return {\r
-                               user: parts[0],\r
-                               repo: parts[1],\r
-                               branch: parts[2],\r
-                               sha: basesha1\r
-                       };\r
-               },\r
-\r
-               _getFileContent: function(githubUrl) {\r
-                       var origFile = GithubAPI.getFile(this.user, githubUrl);\r
-                       if(!origFile.content) {\r
-                               $("<p/>")\r
-                               .text("Unable to locate source file.<br/>" + origFile.status + ": " + origFile.statusText)\r
-                               .modalbox({\r
-                                       title: "Github commit error",\r
-                                       isError: true\r
-                               })\r
-                               .modalbox("open");\r
-                               return;\r
-                       }\r
-                       var base64Content = origFile.content.substring(0, origFile.content.length - 1)\r
-                       return base64Content.base64Decode();\r
-               },\r
-\r
-               _mergeComment: function(fileContent, comment, location) {\r
-                       // replace comment in file content\r
-                       var res = new String();\r
-                       var lines = fileContent.split("\n");\r
-                       // copy lines fron 0 to lstart\r
-                       for(var i = 0; i < location.lstart - 1; i++) {\r
-                               res += lines[i] + "\n";\r
-                       }\r
-                       // set comment\r
-                       if(comment && comment != "") {\r
-                               var commentLines = comment.split("\n");\r
-                               for(var i = 0; i < commentLines.length; i++) {\r
-                                       var line = commentLines[i];\r
-                                       var tab = location.tabpos > 1 ? "\t" : "";\r
-                                       res += tab + (line.length > 0 ? "# " : "#") + line + "\n";\r
-                               }\r
-                       }\r
-                       // copy lines fron lend to end\r
-                       for(var i = location.lend - 1; i < lines.length; i++) {\r
-                               res += lines[i];\r
-                               if(i < lines.length - 1) { res += "\n"; }\r
-                       }\r
-                       return res;\r
-               },\r
-\r
-               /* events */\r
-\r
-               _openCommentBox: function(event, baseArea) {\r
-                       baseArea.commentbox("open", this.user);\r
-               },\r
-\r
-               _doCancelRequest: function(event, baseArea, request) {\r
-                       this._closePullRequest(request.request.number);\r
-                       this._reloadComments();\r
-               },\r
-\r
-               _doUpdateRequest: function(event, baseArea, request) {\r
-                       baseArea.commentbox("open", this.user, request.request.number);\r
-               },\r
-       }\r
-\r
-       // Get github plugin data\r
-       var upstream = $("body").attr("data-github-upstream");\r
-       var basesha1 = $("body").attr("data-github-base-sha1");\r
-       if(upstream && basesha1) {\r
-               GithubUI.init(upstream, basesha1);\r
-       }\r
-});\r
diff --git a/share/nitdoc/js/plugins/github/commentbox.js b/share/nitdoc/js/plugins/github/commentbox.js
deleted file mode 100644 (file)
index 2bb6a18..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-*/\r
-\r
-/*\r
- * CommentBox allows user to edit comments then preview, commit or cancel the changes\r
- */\r
-define([\r
-       "jquery",\r
-       "jQueryUI"\r
-], function($) {\r
-       var Location = function(location) {\r
-               var parts = location.split(":");\r
-               this.origin = location;\r
-               this.path = parts[0];\r
-               this.lstart = parseInt(parts[1].split("--")[0].split(",")[0]);\r
-               this.tabpos = parseInt(parts[1].split("--")[0].split(",")[1]);\r
-               this.lend = parseInt(parts[1].split("--")[1].split(",")[0]);\r
-               this.toString = function() {\r
-                       return this.path + ":" + this.lstart + "," + this.tabpos + "--" + this.lend + ",0";\r
-               }\r
-       }\r
-\r
-       $.widget("nitdoc.commentbox", {\r
-\r
-               options: {\r
-                       previewTxt: "preview",\r
-                       commitTxt: "Commit",\r
-                       cancelTxt: "Cancel",\r
-                       commentboxTitle: "Edit comment",\r
-                       messageTxt: "Commit message"\r
-               },\r
-\r
-               _create: function() {\r
-                       this._id = $(".nitdoc-github-commentbox").length\r
-                       this._oldComment = this.element.val();\r
-                       this._namespace = this.element.data("comment-namespace");\r
-                       this._location = new Location(this.element.data("comment-location"));\r
-                       this.commentBox = $("<div/>")\r
-                       .hide()\r
-                       .addClass("nitdoc-github-commentbox")\r
-                       .append(\r
-                               $("<h3/>")\r
-                               .text(this.options.commentboxTitle)\r
-                       )\r
-                       .append(\r
-                               $("<dl/>")\r
-                               .addClass("nitdoc-github-commentbox-fields")\r
-                               .append(\r
-                                       $("<dd/>")\r
-                                       .append(\r
-                                               $("<textarea/>")\r
-                                               .attr("id", "nitdoc-github-commentbox-comment" + this._id)\r
-                                               .addClass("nitdoc-github-commentarea")\r
-                                               .keyup($.proxy(this._doKeyUp, this))\r
-                                               .keydown($.proxy(this._doKeyDown, this))\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<dt/>")\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr("for", "nitdoc-github-commentbox-message" + this._id)\r
-                                               .text(this.options.messageTxt + ":")\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<dd/>")\r
-                                       .append(\r
-                                               $("<textarea/>")\r
-                                               .attr("id", "nitdoc-github-commentbox-message" + this._id)\r
-                                               .keyup($.proxy(this._doKeyUp, this))\r
-                                               .keydown($.proxy(this._doKeyDown, this))\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<dt/>")\r
-                                       .append(\r
-                                               $("<input/>")\r
-                                               .attr({\r
-                                                       id: "nitdoc-github-commentbox-signedoff" + this._id,\r
-                                                       type: "checkbox"\r
-                                               })\r
-                                               .change($.proxy(this._doSignedChange, this))\r
-                                       )\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr({\r
-                                                       "id": "nitdoc-github-commentbox-signedoff-label" + this._id,\r
-                                                       "for": "nitdoc-github-commentbox-signedoff" + this._id\r
-                                               })\r
-                                       )\r
-                               )\r
-                       )\r
-                       this._buildButtonBar();\r
-                       this.element.after(this.commentBox);\r
-               },\r
-\r
-               _buildButtonBar: function() {\r
-                       this.commentBox.append(\r
-                               $("<div/>")\r
-                               .addClass("nitdoc-github-commentbox-buttons")\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .addClass("nitdoc-github-preview")\r
-                                       .html(this.options.previewTxt)\r
-                                       .click($.proxy(this._doPreviewClick, this))\r
-                               )\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .addClass("nitdoc-github-button")\r
-                                       .addClass("nitdoc-github-commit")\r
-                                       .attr("disabled", "disabled")\r
-                                       .html(this.options.commitTxt)\r
-                                       .click($.proxy(this._doCommitClick, this))\r
-                               )\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .addClass("nitdoc-github-button")\r
-                                       .addClass("nitdoc-github-cancel")\r
-                                       .html(this.options.cancelTxt)\r
-                                       .click($.proxy(this._doCancelClick, this))\r
-                               )\r
-                       );\r
-               },\r
-\r
-               /* public actions */\r
-\r
-               open: function(user, requestID) {\r
-                       this._requestID = requestID;\r
-                       var value = this.element.val();\r
-                       var isNew = !value;\r
-                       var message = "doc: " + (isNew ? "added" : "modified") + " comment for " + this._namespace;\r
-                       this._setMessage(message);\r
-                       this._setSignedOff("Signed-off-by: " + user.signedOff);\r
-                       this._setComment(value);\r
-                       this.commentBox.show();\r
-                       this.commentBox.find("textarea").width(this.commentBox.innerWidth() - 45)\r
-                       $("#nitdoc-github-commentbox-comment" + this._id).focus();\r
-                       $("#nitdoc-github-commentbox-comment" + this._id).trigger("keyup");\r
-                       $("#nitdoc-github-commentbox-message" + this._id).trigger("keyup");\r
-                       this._trigger("_open", null, {commentBox: this});\r
-               },\r
-\r
-               close: function() {\r
-                       this.commentBox.hide();\r
-                       this._trigger("_close", null, {commentBox: this});\r
-               },\r
-\r
-               /* internals */\r
-\r
-               _setComment: function(value) {\r
-                       $("#nitdoc-github-commentbox-comment" + this._id).val(value);\r
-               },\r
-\r
-               _getComment: function() {\r
-                       return $("#nitdoc-github-commentbox-comment" + this._id).val();\r
-               },\r
-\r
-               _getMessage: function() {\r
-                       return $("#nitdoc-github-commentbox-message" + this._id).val();\r
-               },\r
-\r
-               _setMessage: function(message) {\r
-                       $("#nitdoc-github-commentbox-message" + this._id).val(message);\r
-               },\r
-\r
-               _getSignedOff: function() {\r
-                       return $("#nitdoc-github-commentbox-signedoff" + this._id).val();\r
-               },\r
-\r
-               _setSignedOff: function(signedoff) {\r
-                       $("#nitdoc-github-commentbox-signedoff" + this._id).val(signedoff);\r
-                       $("#nitdoc-github-commentbox-signedoff-label" + this._id).text(signedoff);\r
-               },\r
-\r
-               /* events */\r
-\r
-               _doKeyUp: function(event) {\r
-                       $(event.target).height($(event.target).val().split(/\r|\n/).length * 16);\r
-               },\r
-\r
-               _doKeyDown: function(event) {\r
-                       if(event.keyCode == 13){\r
-                               $(event.target).css("height", ($(event.target).outerHeight() + 6) + "px");\r
-                       }\r
-               },\r
-\r
-               _doSignedChange: function(event) {\r
-                       if ($(event.currentTarget).is(':checked')) {\r
-                               this.commentBox.find("button.nitdoc-github-commit").removeAttr("disabled");\r
-                       } else {\r
-                               this.commentBox.find("button.nitdoc-github-commit").attr("disabled", "disabled");\r
-                       }\r
-               },\r
-\r
-               _doPreviewClick: function(event) {\r
-                       this._trigger("_preview", event, {\r
-                               value: this._getComment(),\r
-                               message: this._getMessage() + "\n\n" + this._getSignedOff()\r
-                       });\r
-               },\r
-\r
-               _doCommitClick: function() {\r
-                       this._trigger("_commit", event, {\r
-                               requestID: this._requestID,\r
-                               location: this._location,\r
-                               namespace: this._namespace,\r
-                               oldComment: this._oldComment,\r
-                               newComment: this._getComment(),\r
-                               title: this._getMessage(),\r
-                               message: this._getMessage() + "\n\n" + this._getSignedOff()\r
-                       });\r
-               },\r
-\r
-               _doCancelClick: function() {\r
-                       this.close();\r
-               }\r
-       });\r
-});\r
diff --git a/share/nitdoc/js/plugins/github/loginbox.js b/share/nitdoc/js/plugins/github/loginbox.js
deleted file mode 100644 (file)
index 55fbffe..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-*/\r
-\r
-/*\r
- * LoginBox allows user to login and logoff from GitHub API\r
- */\r
-define([\r
-       "jquery",\r
-       "jQueryUI"\r
-], function($) {\r
-       $.widget("nitdoc.loginbox", {\r
-               options: {\r
-                       icon: "resources/icons/github-icon.png",\r
-                       iconActive: "resources/icons/github-icon-green.png",\r
-                       iconAlt: "GitHub",\r
-                       signedinTxt: "Signed in Github",\r
-                       signedoutTxt: "Sign in Github",\r
-                       welcomeTxt: "Hello",\r
-                       upstreamTxt: "Upstream branch",\r
-                       baseTxt: "Base",\r
-                       signoffTxt: "Sign Off",\r
-                       usernameTxt: "Username",\r
-                       passwordTxt: "Password",\r
-                       repoTxt: "Repository",\r
-                       branchTxt: "Branch",\r
-                       signinTxt: "Sign In"\r
-               },\r
-\r
-               _create: function() {\r
-                       this.element.append(\r
-                               $("<span/>")\r
-                               .addClass("glyphicon glyphicon-off")\r
-                               //.click($.proxy(this.toggle, this))\r
-                               .attr({\r
-                                       "data-container": "body",\r
-                                       "data-toggle": "popover",\r
-                                       "data-placement": "bottom",\r
-                                       "data-content": "bottom",\r
-                                       "data-html": "true",\r
-                               })\r
-                       );\r
-\r
-                       this.content = $("<div/>");\r
-                       this.loginBox = $("<div/>")\r
-                       .attr("id", "nitdoc-github-loginbox")\r
-                       .css("display", "none")\r
-                       .append(\r
-                               $(document.createElement("div"))\r
-                               .addClass("nitdoc-github-loginbox-arrow")\r
-                               .append("&nbsp;")\r
-                       )\r
-                       .append(this.content);\r
-                       this.element.append(this.loginBox);\r
-               },\r
-\r
-               /* public actions */\r
-\r
-               displayLogout: function(origin, user) {\r
-                       this.content.empty();\r
-                       this.content.append(\r
-                               $("<h3/>").text(this.options.signedinTxt)\r
-                       )\r
-                       this.content.append(\r
-                               $("<div/>")\r
-                               .append(\r
-                                       $("<h4/>")\r
-                                       .append(this.options.welcomeTxt + " ")\r
-                                       .append(\r
-                                               $("<a/>")\r
-                                               .attr("href", "https://github.com/" + user.login)\r
-                                               .append(user.login)\r
-                                       ).append(",")\r
-                               )\r
-                               .append(\r
-                                       $("<label/>")\r
-                                       .text("Upstream Branch")\r
-                               )\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .text(origin.user + ":" + origin.repo + ":" + origin.branch)\r
-                                       .addClass("nitdoc-github-loginbox-githublink")\r
-                                       .attr({\r
-                                               title: "Open branch in GitHub",\r
-                                               href: "https://github.com/" + origin.user + "/" + origin.repo + "/tree/" + origin.branch\r
-                                       })\r
-                               )\r
-                               .append(\r
-                                       $("<label/>")\r
-                                       .attr("for", "github-base")\r
-                                       .append("Your branch")\r
-                               )\r
-                               .append(\r
-                                       $("<a/>")\r
-                                       .text(user.login + ":" + user.repo + ":" + user.branch)\r
-                                       .addClass("nitdoc-github-loginbox-githublink")\r
-                                       .attr({\r
-                                               title: "Open branch in GitHub",\r
-                                               href: "https://github.com/" + user.login + "/" + user.repo + "/tree/" + user.branch\r
-                                       })\r
-                               )\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .addClass("nitdoc-github-button")\r
-                                       .addClass("nitdoc-github-cancel")\r
-                                       .append(\r
-                                               $("<img/>")\r
-                                               .attr("src", this.options.icon)\r
-                                       ).text(this.options.signoffTxt)\r
-                                       .click($.proxy(this._doClickLogoff, this))\r
-                               )\r
-                       );\r
-                       $(".nitdoc-github-li-img").attr("src", this.options.iconActive);\r
-               },\r
-\r
-               displayLogin: function() {\r
-                       this.content.empty();\r
-                       this.content.append(\r
-                               $("<h3/>").text(this.options.signedoutTxt)\r
-                       )\r
-                       this.content.append(\r
-                               $("<form/>")\r
-                               .keyup($.proxy(this._doFormChange, this))\r
-                               .append(\r
-                                       $("<div/>")\r
-                                       .addClass("form-group")\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr("for", "nitdoc-github-login-field")\r
-                                               .append(this.options.usernameTxt)\r
-                                       )\r
-                                       .addClass("form-group")\r
-                                       .append(\r
-                                               $("<input/>")\r
-                                               .attr({\r
-                                                       id: "nitdoc-github-login-field",\r
-                                                       type: "text",\r
-                                                       "class": "form-control"\r
-                                               })\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<div/>")\r
-                                       .addClass("form-group")\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr("for", "nitdoc-github-password-field")\r
-                                               .append(this.options.passwordTxt)\r
-                                       )\r
-                                       .append(\r
-                                               $("<input/>")\r
-                                               .attr({\r
-                                                       id: "nitdoc-github-password-field",\r
-                                                       type: "password",\r
-                                                       "class": "form-control"\r
-                                               })\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<div/>")\r
-                                       .addClass("form-group")\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr("for", "nitdoc-github-repo-field")\r
-                                               .append(this.options.repoTxt)\r
-                                       )\r
-                                       .append(\r
-                                               $("<input/>")\r
-                                               .attr({\r
-                                                       id: "nitdoc-github-repo-field",\r
-                                                       type: "text",\r
-                                                       "class": "form-control"\r
-                                               })\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<div/>")\r
-                                       .addClass("form-group")\r
-                                       .append(\r
-                                               $("<label/>")\r
-                                               .attr("for", "nitdoc-github-branch-field")\r
-                                               .append(this.options.branchTxt)\r
-                                       )\r
-                                       .append(\r
-                                               $("<input/>")\r
-                                               .attr({\r
-                                                       id: "nitdoc-github-branch-field",\r
-                                                       type: "text",\r
-                                                       "class": "form-control"\r
-                                               })\r
-                                       )\r
-                               )\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .addClass("nitdoc-github-button btn btn-primary btn-lg pull-right")\r
-                                       .attr("disabled", "disabled")\r
-                                       .append(\r
-                                               $("<img/>")\r
-                                               .attr("src", this.options.icon)\r
-                                       ).text(this.options.signinTxt)\r
-                                       .click($.proxy(this._doClickLogin, this))\r
-                               )\r
-                       );\r
-                       $(".nitdoc-github-li-img").attr("src", this.options.icon);\r
-               },\r
-\r
-               toggle: function() {\r
-                       if(this.loginBox.is(':hidden')) {\r
-                               this.loginBox.show();\r
-                               if ($('#nitdoc-github-login-field').is(':visible')) { $('#nitdoc-github-login-field').focus(); }\r
-                       } else {\r
-                               this.loginBox.hide();\r
-                       }\r
-               },\r
-\r
-               /* events */\r
-\r
-               _doClickLogoff: function(event) {\r
-                       this._trigger("_logoff", event);\r
-               },\r
-\r
-               _doClickLogin: function(event) {\r
-                       this._trigger("_login", event, {\r
-                               login: $('#nitdoc-github-login-field').val(),\r
-                               password: $('#nitdoc-github-password-field').val(),\r
-                               repo: $('#nitdoc-github-repo-field').val(),\r
-                               branch: $('#nitdoc-github-branch-field').val()\r
-                       });\r
-                       return false;\r
-               },\r
-\r
-               _doFormChange: function(event) {\r
-                       login = $('#nitdoc-github-login-field').val();\r
-                       password = $('#nitdoc-github-password-field').val();\r
-                       repo = $('#nitdoc-github-repo-field').val();\r
-                       branch = $('#nitdoc-github-branch-field').val();\r
-                       if(login && password && repo && branch) {\r
-                               this.loginBox.find("form .nitdoc-github-button").removeAttr("disabled");\r
-                       } else {\r
-                               this.loginBox.find("form .nitdoc-github-button").attr("disabled", "disabled");\r
-                       }\r
-               }\r
-       });\r
-});\r
diff --git a/share/nitdoc/js/plugins/modalbox.js b/share/nitdoc/js/plugins/modalbox.js
deleted file mode 100644 (file)
index 71bbbad..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-define([\r
-       "jquery",\r
-       "jQueryUI"\r
-], function($) {\r
-       $.widget("nitdoc.modalbox", {\r
-               options: {\r
-                       id: "nitdoc-dialog",\r
-                       classes: "nitdoc-dialog",\r
-                       css: {},\r
-                       title: "Title",\r
-                       isError: false,\r
-               },\r
-\r
-               _create: function() {\r
-                       this._addFade();\r
-                       this._makeDialog();\r
-               },\r
-\r
-               open: function() {\r
-                       this._dialog\r
-                       .show()\r
-                       .css({\r
-                               top: "50%",\r
-                               marginTop: -(this._dialog.outerHeight() / 2) + "px",\r
-                               left: "50%",\r
-                               marginLeft: -(this._dialog.outerWidth() / 2) + "px"\r
-                       })\r
-                       .find(".nitdoc-dialog-buttons button:first").focus();\r
-\r
-                       this._fade.show();\r
-               },\r
-\r
-               close: function() {\r
-                       this._fade.hide();\r
-                       this._dialog.hide();\r
-               },\r
-\r
-               _addFade: function() {\r
-                       this._fade = $("<div/>")\r
-                       .hide()\r
-                       .attr("id", "nitdoc-dialog-fade-" + this.options.id)\r
-                       .addClass("nitdoc-dialog-fade");\r
-                       $("body").append(this._fade);\r
-               },\r
-\r
-               _makeDialog: function() {\r
-                       this._dialog = $("<div/>")\r
-                       .hide()\r
-                       .attr("id", this.options.id)\r
-                       .addClass(this.options.classes)\r
-                       .css(this.options.css)\r
-                       .append(\r
-                               $("<div/>")\r
-                               .addClass("nitdoc-dialog-header")\r
-                               .append(\r
-                                       $("<h3/>")\r
-                                       .text(this.options.title)\r
-                               )\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .addClass("nitdoc-dialog-close")\r
-                                       .append("x")\r
-                                       .click($.proxy(this.close, this))\r
-                               )\r
-                       )\r
-                       .append(\r
-                               $("<div/>")\r
-                               .addClass("nitdoc-dialog-content")\r
-                               .html(this.element)\r
-                       )\r
-                       .append(\r
-                               $("<div/>")\r
-                               .addClass("nitdoc-dialog-buttons")\r
-                               .append(\r
-                                       $("<button/>")\r
-                                       .append("Ok")\r
-                                       .click($.proxy(this.close, this))\r
-                               )\r
-                       );\r
-                       if(this.options.isError) {\r
-                               this._dialog.addClass("nitdoc-dialog-error");\r
-                       }\r
-                       $("body").append(this._dialog);\r
-               }\r
-       });\r
-});\r
diff --git a/share/nitdoc/js/plugins/quicksearch.js b/share/nitdoc/js/plugins/quicksearch.js
deleted file mode 100644 (file)
index f8cd520..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/* 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.
-
-   Documentation generator for the nit language.
-   Generate API documentation in HTML format from nit source code.
-*/
-
-/*
- * Nitdoc QuickSearch widget
- */
-$.widget("nitdoc.quicksearch", {
-
-       options: {
-               list: {}, // List of raw results generated by nitdoc tool
-               fieldAttrs: {
-                       autocomplete: "off",
-               },
-               tableID: "nitdoc-qs-table",
-               tableCSS: {
-                       "position": "absolute"
-               },
-               rowClass: "nitdoc-qs-row",
-               rowCatClass: "nitdoc-qs-cat",
-               rowSubClass: "nitdoc-qs-sub",
-               rowActiveClass: "nitdoc-qs-active",
-               rowOverflowClass: "nitdoc-qs-overflow",
-               rowOverflowActive: "nitdoc-qs-overflow-active",
-               rowNoResultClass: "nitdoc-qs-noresult",
-               overflowUpHtml: "&#x25B2;",
-               overflowDownHtml: "&#x25BC;",
-               noresultText: "Sorry, there is no match, best results are:",
-               infoClass: "nitdoc-qs-info",
-               gotoPage: "search.html",
-               maxSize: 10
-       },
-
-       _create: function() {
-               // set widget options
-               this.element.attr(this.options.fieldAttrs);
-               // event dispatch
-               this._on(this.element, {
-                       "keydown": this._doKeyDown,
-                       "keyup": this._doKeyUp,
-                       "input": this._doInput
-               });
-               // add result table element once
-               this._table = $("<table/>")
-                       .attr("id", this.options.tableID)
-                       .css(this.options.tableCSS)
-                       .css("min-width", this.element.outerWidth());
-               $("body").append(this._table);
-               // make table disappear when a click occurs outside
-               $(document).click($.proxy(this.closeTable, this));
-       },
-
-       /* events */
-
-       _doKeyDown: function(event) {
-               switch(event.keyCode) {
-                       case 38: // Up
-                               this._selectPrev();
-                               return false;
-                       case 40: // Down
-                               this._selectNext();
-                               return false;
-                       default:
-                               return true;
-                }
-       },
-
-       _doKeyUp: function(event) {
-               switch(event.keyCode) {
-                       case 38: // Up
-                       case 40: // Down
-                               break;
-                       case 13: // Enter
-                               this._loadResult();
-                               return false;
-                       case 27: // Escape
-                               this.element.blur();
-                               this.closeTable();
-                               return true;
-                       default: // Other keys
-                               return true;
-               }
-       },
-
-       _doInput: function(event) {
-               Utils.delayEvent($.proxy(this.search, this));
-       },
-
-       /* Result lookup */
-
-       _getResults: function(query) {
-               var results = {};
-               results.matches = [];
-               for(var entry in this.options.list) {
-                       if(!entry.startsWith(query, true)) {
-                               continue;
-                       }
-                       var cat = {
-                               name: entry,
-                               entries: this.options.list[entry]
-                       };
-                       results.matches[results.matches.length] = cat;
-
-                       if(entry == query) {
-                               cat.rank = 3;
-                       } else if(entry.toUpperCase() == query.toUpperCase()) {
-                               cat.rank = 2;
-                       } else {
-                               cat.rank = 1 + query.dice(entry);
-                       }
-               }
-               results.matches.sort(this._rankSorter);
-               results.partials = new Array();
-               if(results.matches.length == 0) {
-                       for(var entry in this.options.list) {
-                               var cat = {
-                                       name: entry,
-                                       entries: this.options.list[entry]
-                               }
-                               cat.rank = query.dice(entry);
-                               if(cat.rank > 0) {
-                                       results.partials[results.partials.length] = cat;
-                               }
-                       }
-                       results.partials.sort(this._rankSorter);
-               }
-               return results;
-       },
-
-       _rankSorter: function(a, b){
-               if(a.rank < b.rank) {
-                       return 1;
-               } else if(a.rank > b.rank) {
-                       return -1;
-               }
-               return 0;
-       },
-
-       /* Results table */
-
-       search: function() {
-               var query = this.element.val();
-               if(query) {
-                       var results = this._getResults(query);
-                       this.openTable(query, results);
-               }
-       },
-
-       openTable: function(query, results) {
-               this._table.empty();
-               this._rows = [];
-               this._index = -1;
-
-               var resultSet = results.matches;
-               if(resultSet.length == 0) {
-                       resultSet = results.partials
-               }
-
-               for(var i in resultSet) {
-                       var cat = resultSet[i];
-                       var result = cat.entries[0];
-                       this.addRow(cat.name, result.txt, result.url, this.options.rowCatClass)
-                       for(var j = 1; j < cat.entries.length; j++) {
-                               var result = cat.entries[j];
-                               this.addRow(cat.name, result.txt, result.url, this.options.rowSubClass)
-                       }
-               }
-
-               if(this._rows.length >= this.options.maxSize) {
-                       this.addOverflowUp();
-                       this.addOverflowDown();
-               }
-               if(results.matches.length == 0) {
-                       this.addNoResultRow();
-               }
-
-               if(resultSet.length > 0) {
-                       this._setIndex(0);
-               }
-               this._table.show();
-               this._autosizeTable();
-       },
-
-       closeTable: function(target) {
-               if(target != this.element && target != this._table) {
-                       this._table.hide();
-               }
-       },
-
-       addRow: function(name, txt, url, cls) {
-               var row = $("<tr/>")
-                       .addClass(this.options.rowClass)
-                       .data("searchDetails", {name: name, url: url})
-                       .data("index", this._rows.length)
-                       .append(
-                               $("<td/>")
-                                       .html(name)
-                                       .addClass(cls)
-                       )
-                       .append(
-                               $("<td/>")
-                                       .html(txt + "&nbsp;&raquo;")
-                                       .addClass(this.options.infoClass)
-                       )
-                       .mouseover($.proxy(this._mouseOverRow, this))
-                       .click($.proxy(this._clickRow, this))
-               this._rows.push(row);
-               if(this._rows.length >= this.options.maxSize) {
-                       row.hide();
-               }
-               this._table.append(row);
-       },
-
-       addOverflowUp: function() {
-               this._table.prepend(
-                       $("<tr/>")
-                               .addClass(this.options.rowOverflowClass)
-                               .append(
-                                       $("<td/>")
-                                               .attr("colspan", 2)
-                                               .html(this.options.overflowUpHtml)
-                               )
-                               .click($.proxy(this._clickPrev, this))
-               );
-       },
-
-       addOverflowDown: function() {
-               this._table.append(
-                       $("<tr/>")
-                               .addClass(this.options.rowOverflowClass)
-                               .addClass(this.options.rowOverflowActive)
-                               .append(
-                                       $("<td/>")
-                                               .attr("colspan", 2)
-                                               .html(this.options.overflowDownHtml)
-                               )
-                               .click($.proxy(this._clickNext, this))
-               );
-       },
-
-       addNoResultRow: function() {
-               this._table.prepend(
-                       $("<tr/>")
-                       .addClass(this.options.rowNoResultClass)
-                       .append(
-                               $("<td/>")
-                               .attr("colspan", "2")
-                               .text(this.options.noresultText)
-                       )
-               );
-       },
-
-       _autosizeTable: function() {
-               this._table.position({
-                       my: "right top",
-                       at: "right bottom",
-                       of: this.element
-               });
-       },
-
-       _hasIndex: function(index) {
-               return index >= 0 && index < this._rows.length;
-       },
-
-       _hasPrev: function(index) {
-               return index - 1 >= 0;
-       },
-
-       _hasNext: function(index) {
-               return index + 1 < this._rows.length;
-       },
-
-       _setIndex: function(index) {
-               if(this._hasIndex(this._index)) {
-                       this._rows[this._index].removeClass(this.options.rowActiveClass);
-               }
-               this._index = index;
-               if(this._hasIndex(this._index)) {
-                       this._rows[this._index].addClass(this.options.rowActiveClass);
-               }
-       },
-
-       _selectPrev: function() {
-               if(this._hasPrev(this._index)) {
-                       this._setIndex(this._index - 1);
-                       if(!this._rows[this._index].is(":visible")) {
-                               this._table.find("tr." + this.options.rowClass + ":visible").last().hide();
-                               this._table.find("tr." + this.options.rowOverflowClass).addClass(this.options.rowOverflowActive);
-                               this._rows[this._index].show();
-                               if(!this._hasPrev(this._index)) {
-                                       this._table.find("tr." + this.options.rowOverflowClass).removeClass(this.options.rowOverflowActive);
-                               }
-                               this._autosizeTable();
-                       }
-               }
-       },
-
-       _selectNext: function() {
-               if(this._hasNext(this._index)) {
-                       this._setIndex(this._index + 1);
-                       if(!this._rows[this._index].is(":visible")) {
-                               this._table.find("tr." + this.options.rowClass + ":visible").first().hide();
-                               this._table.find("tr." + this.options.rowOverflowClass).addClass(this.options.rowOverflowActive);
-                               this._rows[this._index].show();
-                               if(!this._hasNext(this._index)) {
-                                       this._table.find("tr." + this.options.rowOverflowClass).removeClass(this.options.rowOverflowActive);
-                               }
-                               this._autosizeTable();
-                       }
-               }
-       },
-
-       // Load selected search result page
-       _loadResult: function() {
-               if(this._index > -1) {
-                       window.location = this._rows[this._index].data("searchDetails").url;
-                       return;
-               }
-               if(this.element.val().length == 0) { return; }
-
-               window.location = this.options.gotoPage + "#q=" + this.element.val();
-               if(window.location.href.indexOf(this.options.gotoPage) > -1) {
-                       location.reload();
-               }
-       },
-
-       /* table events */
-
-       _clickNext: function(event) {
-               event.stopPropagation();
-               this._selectNext();
-       },
-
-       _clickPrev: function(event) {
-               event.stopPropagation();
-               this._selectPrev();
-       },
-
-       _clickRow: function(event) {
-               window.location = $(event.currentTarget).data("searchDetails")["url"];
-       },
-
-       _mouseOverRow: function(event) {
-               this._setIndex($(event.currentTarget).data("index"));
-       }
-});
-
-var searchField = $("<input/>")
-.addClass("form-control input-sm")
-.attr({
-       id: "nitdoc-qs-field",
-       type: "text",
-       placeholder: "Search..."
-})
-
-$("#topmenu-collapse").append(
-       $("<div>")
-       .addClass("navbar-form navbar-right")
-       .append(
-               $("<div>")
-               .addClass("form-group")
-               .append(searchField)
-       )
-);
-
-searchField.quicksearch({
-       list: this.nitdocQuickSearchRawList
-});
diff --git a/share/nitdoc/resources/icons/github-icon-green.png b/share/nitdoc/resources/icons/github-icon-green.png
deleted file mode 100644 (file)
index d291056..0000000
Binary files a/share/nitdoc/resources/icons/github-icon-green.png and /dev/null differ
diff --git a/share/nitdoc/resources/icons/github-icon-white.png b/share/nitdoc/resources/icons/github-icon-white.png
deleted file mode 100644 (file)
index 98ae072..0000000
Binary files a/share/nitdoc/resources/icons/github-icon-white.png and /dev/null differ
diff --git a/share/nitdoc/resources/icons/github-icon.png b/share/nitdoc/resources/icons/github-icon.png
deleted file mode 100644 (file)
index 8b25551..0000000
Binary files a/share/nitdoc/resources/icons/github-icon.png and /dev/null differ
index 9b295be..34ec170 100644 (file)
@@ -17,6 +17,7 @@
        <div class='card-body' ng-if='mentity.class_name != "MPackage"'>
                <h5 class='card-heading'>
                        <entity-signature mentity='mentity' />
+                       <small><br/><entity-namespace namespace='mentity.namespace' /></small>
                </h5>
                <span class='synopsis' ng-bind-html='mentity.html_synopsis' />
        </div>
index a4d06a6..949a6e3 100644 (file)
@@ -9,7 +9,7 @@
                <entity-card ng-click='vm.selectEnter()' ng-class='{active: vm.activeItem == $index}' ng-mouseover='vm.setActive($index)' mentity='mentity' ng-repeat='mentity in vm.results.results' />
                <div class='card' ng-click='vm.selectEnter()' ng-mouseover='vm.setActive(vm.results.results.length)' ng-class='{active: vm.activeItem == vm.results.results.length}'>
                        <div class='card-body'>
-                               Show all {{vm.results.total}} results for <a>"{{vm.query}}"</a>
+                               Show all {{vm.results.count}} results for <a>"{{vm.query}}"</a>
                        </div>
                </div>
        </div>
index 433b73d..54d9471 100644 (file)
@@ -13,7 +13,7 @@
 <br><br>
 <div class='container'>
        <div ng-if='vm.maintaining.results.length > 0'>
-               <h3 id='maintaining'>{{vm.maintaining.total}} maintained projects</h3>
+               <h3 id='maintaining'>{{vm.maintaining.count}} maintained projects</h3>
                <div class='card-list'>
                        <entity-card mentity='package' ng-repeat='package in vm.maintaining.results' />
                </div>
@@ -22,7 +22,7 @@
                </div>
        </div>
        <div ng-if='vm.contributing.results.length > 0'>
-               <h3 id='contributing'>{{vm.contributing.total}} contributed projects</h3>
+               <h3 id='contributing'>{{vm.contributing.count}} contributed projects</h3>
                <div class='card-list'>
                        <entity-card mentity='package' ng-repeat='package in vm.contributing.results' />
                </div>
index 6614e9c..ddf9f4c 100644 (file)
@@ -1,6 +1,6 @@
 <div class='container'>
        <h2>
-               {{vm.entities.total}} matches for
+               {{vm.entities.count}} matches for
                <a ui-sref='search({q: vm.query})'>{{vm.query}}</a>
        </h2>
        <div class='card-list'>
index 8d3b867..8086bfd 100644 (file)
@@ -16,7 +16,7 @@
 
 NITCOPT=--semi-global
 OLDNITCOPT=--semi-global
-OBJS=nitc nitpick nit nitls nitunit nitpm nitx nitlight nitserial nitrestful
+OBJS=nitc nitpick nit nitls nitunit nitpm nitx nitlight nitserial nitrestful nitpackage
 SRCS=$(patsubst %,%.nit,$(OBJS))
 BINS=$(patsubst %,../bin/%,$(OBJS))
 MOREOBJS=nitdoc nitweb nitcatalog nitmetrics nitpretty nitweb
index dd891ac..140278e 100644 (file)
@@ -165,24 +165,6 @@ class Person
                return email.md5.to_lower
        end
 
-       # Return a full-featured link to a person
-       fun to_html: String
-       do
-               var res = ""
-               var e = name.html_escape
-               var page = self.page
-               if page != null then
-                       res += "<a href=\"{page.html_escape}\">"
-               end
-               var gravatar = self.gravatar
-               if gravatar != null then
-                       res += "<img src=\"https://secure.gravatar.com/avatar/{gravatar}?size=20&amp;default=retro\">&nbsp;"
-               end
-               res += e
-               if page != null then res += "</a>"
-               return res
-       end
-
        # The standard representation of a person.
        #
        # ~~~
@@ -586,6 +568,20 @@ class CatalogStats
 
        # Number of line of codes
        var loc = 0
+
+       # Return the stats as a Map associating each stat key to its value
+       fun to_map: Map[String, Int] do
+               var map = new HashMap[String, Int]
+               map["packages"] = packages
+               map["maintainers"] = maintainers
+               map["contributors"] = contributors
+               map["tags"] = tags
+               map["modules"] = modules
+               map["classes"] = classes
+               map["methods"] = methods
+               map["loc"] = loc
+               return map
+       end
 end
 
 # MPackage statistics for the catalog
diff --git a/src/catalog/catalog_json.nit b/src/catalog/catalog_json.nit
deleted file mode 100644 (file)
index da1bcfc..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-# 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.
-
-# Translate catalog entities to JSON
-module catalog_json
-
-import catalog
-
-redef class MPackageMetadata
-       serialize
-
-       redef fun core_serialize_to(v) do
-               super
-               v.serialize_attribute("license", license)
-               v.serialize_attribute("maintainers", maintainers)
-               v.serialize_attribute("contributors", contributors)
-               v.serialize_attribute("tags", tags)
-               v.serialize_attribute("tryit", tryit)
-               v.serialize_attribute("apk", apk)
-               v.serialize_attribute("homepage", homepage)
-               v.serialize_attribute("browse", browse)
-               v.serialize_attribute("git", git)
-               v.serialize_attribute("issues", issues)
-               v.serialize_attribute("first_date", first_date)
-               v.serialize_attribute("last_date", last_date)
-       end
-end
-
-# Catalog statistics
-redef class CatalogStats
-       serialize
-
-       redef fun core_serialize_to(v) do
-               super
-               v.serialize_attribute("packages", packages)
-               v.serialize_attribute("maintainers", maintainers)
-               v.serialize_attribute("contributors", contributors)
-               v.serialize_attribute("tags", tags)
-               v.serialize_attribute("modules", modules)
-               v.serialize_attribute("classes", classes)
-               v.serialize_attribute("methods", methods)
-               v.serialize_attribute("loc", loc)
-       end
-end
-
-# MPackage statistics for the catalog
-redef class MPackageStats
-       serialize
-
-       redef fun core_serialize_to(v) do
-               super
-               v.serialize_attribute("mmodules", mmodules)
-               v.serialize_attribute("mclasses", mclasses)
-               v.serialize_attribute("mmethods", mmethods)
-               v.serialize_attribute("loc", loc)
-               v.serialize_attribute("errors", errors)
-               v.serialize_attribute("warnings", warnings)
-               v.serialize_attribute("warnings_per_kloc", warnings_per_kloc)
-               v.serialize_attribute("documentation_score", documentation_score)
-               v.serialize_attribute("commits", commits)
-               v.serialize_attribute("score", score)
-       end
-end
-
-redef class Person
-       serialize
-
-       redef fun core_serialize_to(v) do
-               super
-               v.serialize_attribute("name", name)
-               v.serialize_attribute("email", email)
-               v.serialize_attribute("gravatar", gravatar)
-       end
-end
index cff93bd..75e9cc5 100644 (file)
@@ -39,6 +39,8 @@ redef class ToolContext
        var opt_no_cc = new OptionBool("Do not invoke the C compiler", "--no-cc")
        # --no-main
        var opt_no_main = new OptionBool("Do not generate main entry point", "--no-main")
+       # --shared-lib
+       var opt_shared_lib = new OptionBool("Compile to a native shared library", "--shared-lib")
        # --make-flags
        var opt_make_flags = new OptionString("Additional options to the `make` command", "--make-flags")
        # --max-c-lines
@@ -81,7 +83,7 @@ redef class ToolContext
        redef init
        do
                super
-               self.option_context.add_option(self.opt_output, self.opt_dir, self.opt_run, self.opt_no_cc, self.opt_no_main, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening)
+               self.option_context.add_option(self.opt_output, self.opt_dir, self.opt_run, self.opt_no_cc, self.opt_no_main, self.opt_shared_lib, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening)
                self.option_context.add_option(self.opt_no_check_covariance, self.opt_no_check_attr_isset, self.opt_no_check_assert, self.opt_no_check_autocast, self.opt_no_check_null, self.opt_no_check_all)
                self.option_context.add_option(self.opt_typing_test_metrics, self.opt_invocation_metrics, self.opt_isset_checks_metrics)
                self.option_context.add_option(self.opt_no_stacktrace)
@@ -92,6 +94,7 @@ redef class ToolContext
                self.option_context.add_option(self.opt_trace)
 
                opt_no_main.hidden = true
+               opt_shared_lib.hidden = true
        end
 
        redef fun process_options(args)
@@ -391,6 +394,13 @@ LDLIBS  ?= -lm {{{linker_options.join(" ")}}}
 
                if self.toolcontext.opt_trace.value then makefile.write "LDLIBS += -llttng-ust -ldl\n"
 
+               if toolcontext.opt_shared_lib.value then
+                       makefile.write """
+CFLAGS += -fPIC
+LDFLAGS += -shared -Wl,-soname,{{{outname}}}
+"""
+               end
+
                makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n"
                if platform.supports_libunwind then
                        if toolcontext.opt_no_stacktrace.value then
@@ -782,7 +792,7 @@ struct catch_stack_t {
        int currentSize;
        jmp_buf *envs;
 };
-extern __thread struct catch_stack_t catchStack;
+extern struct catch_stack_t *getCatchStack();
 """
        end
 
@@ -883,7 +893,44 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                v.add_decl("int glob_argc;")
                v.add_decl("char **glob_argv;")
                v.add_decl("val *glob_sys;")
-               v.add_decl("__thread struct catch_stack_t catchStack = \{-1, 0, NULL\};")
+
+               # Store catch stack in thread local storage
+               v.add_decl """
+#if defined(TARGET_OS_IPHONE)
+       // Use pthread_key_create and others for iOS
+       #include <pthread.h>
+
+       static pthread_key_t catch_stack_key;
+       static pthread_once_t catch_stack_key_created = PTHREAD_ONCE_INIT;
+
+       static void create_catch_stack()
+       {
+               pthread_key_create(&catch_stack_key, NULL);
+       }
+
+       struct catch_stack_t *getCatchStack()
+       {
+               pthread_once(&catch_stack_key_created, &create_catch_stack);
+               struct catch_stack_t *data = pthread_getspecific(catch_stack_key);
+               if (data == NULL) {
+                       data = malloc(sizeof(struct catch_stack_t));
+                       data->cursor = -1;
+                       data->currentSize = 0;
+                       data->envs = NULL;
+                       pthread_setspecific(catch_stack_key, data);
+               }
+               return data;
+       }
+#else
+       // Use __thread when available
+       __thread struct catch_stack_t catchStack = {-1, 0, NULL};
+
+       struct catch_stack_t *getCatchStack()
+       {
+               return &catchStack;
+       }
+#endif
+"""
 
                if self.modelbuilder.toolcontext.opt_typing_test_metrics.value then
                        for tag in count_type_test_tags do
@@ -1752,7 +1799,7 @@ abstract class AbstractCompilerVisitor
                var nat = new_var(mtype)
                var byte_esc = new Buffer.with_cap(len * 4)
                for i in [0 .. len[ do
-                       byte_esc.append("\\x{ns[i].to_s.substring_from(2)}")
+                       byte_esc.append("\\x{ns[i].to_hex}")
                end
                self.add("{nat} = \"{byte_esc}\";")
                return nat
@@ -1876,8 +1923,11 @@ abstract class AbstractCompilerVisitor
        # This method should be called before the error messages and before a `add_raw_abort`.
        fun add_raw_throw
        do
-               self.add("if(catchStack.cursor >= 0)\{")
-               self.add("longjmp(catchStack.envs[catchStack.cursor], 1);")
+               self.add("\{")
+               self.add("struct catch_stack_t *catchStack = getCatchStack();")
+               self.add("if(catchStack->cursor >= 0)\{")
+               self.add("      longjmp(catchStack->envs[catchStack->cursor], 1);")
+               self.add("\}")
                self.add("\}")
        end
 
@@ -3521,22 +3571,25 @@ redef class ADoExpr
        redef fun stmt(v)
        do
                if self.n_catch != null then
-                       v.add("if(catchStack.currentSize == 0) \{")
-                       v.add("         catchStack.cursor = -1;")
-                       v.add("         catchStack.currentSize = 100;")
-                       v.add("         catchStack.envs = malloc(sizeof(jmp_buf)*100);")
-                       v.add("\} else if(catchStack.cursor == catchStack.currentSize - 1) \{")
-                       v.add("         catchStack.currentSize *= 2;")
-                       v.add("         catchStack.envs = realloc(catchStack.envs, sizeof(jmp_buf)*catchStack.currentSize);")
+                       v.add("\{")
+                       v.add("struct catch_stack_t *catchStack = getCatchStack();")
+                       v.add("if(catchStack->currentSize == 0) \{")
+                       v.add("         catchStack->cursor = -1;")
+                       v.add("         catchStack->currentSize = 100;")
+                       v.add("         catchStack->envs = malloc(sizeof(jmp_buf)*100);")
+                       v.add("\} else if(catchStack->cursor == catchStack->currentSize - 1) \{")
+                       v.add("         catchStack->currentSize *= 2;")
+                       v.add("         catchStack->envs = realloc(catchStack->envs, sizeof(jmp_buf)*catchStack->currentSize);")
                        v.add("\}")
-                       v.add("catchStack.cursor += 1;")
-                       v.add("if(!setjmp(catchStack.envs[catchStack.cursor]))\{")
+                       v.add("catchStack->cursor += 1;")
+                       v.add("if(!setjmp(catchStack->envs[catchStack->cursor]))\{")
                        v.stmt(self.n_block)
-                       v.add("catchStack.cursor -= 1;")
+                       v.add("catchStack->cursor -= 1;")
                        v.add("\}else \{")
-                       v.add("catchStack.cursor -= 1;")
+                       v.add("catchStack->cursor -= 1;")
                        v.stmt(self.n_catch)
                        v.add("\}")
+                       v.add("\}")
                else
                        v.stmt(self.n_block)
                end
@@ -3766,8 +3819,9 @@ end
 
 redef class ACharExpr
        redef fun expr(v) do
-               if is_ascii then return v.byte_instance(value.as(not null).ascii)
-               if is_code_point then return v.int_instance(value.as(not null).code_point)
+               if is_code_point then
+                       return v.int_instance(value.as(not null).code_point)
+               end
                return v.char_instance(self.value.as(not null))
        end
 end
index a587c59..15b6f05 100644 (file)
@@ -982,7 +982,10 @@ class SeparateCompiler
                                var alloc = v.nit_alloc("sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t)", mclass.full_name)
                                v.add("{res} = {alloc};")
                        end
-                       if modelbuilder.toolcontext.opt_trace.value then v.add("tracepoint(Nit_Compiler, Object_Instance,\"{mtype}\", (intptr_t)self);")
+                       if modelbuilder.toolcontext.opt_trace.value then
+                               v.add("tracepoint(Nit_Compiler, Object_Instance,\"{mtype}\", (uintptr_t)self);")
+                               v.add("GC_register_finalizer(self, object_destroy_callback, NULL, NULL, NULL);")
+                       end
                        v.add("{res}->type = type;")
                        hardening_live_type(v, "type")
                        v.require_declaration("class_{c_name}")
index 244a9ed..511cb75 100644 (file)
@@ -654,6 +654,7 @@ class SeparateErasureCompilerVisitor
                var res = self.new_var(mtype)
                res.is_exact = true
                self.require_declaration("NEW_{nclass.c_name}")
+               length = autobox(length, compiler.mainmodule.int_type)
                self.add("{res} = NEW_{nclass.c_name}({length});")
                return res
        end
index 08406a2..95a6ff0 100644 (file)
@@ -21,8 +21,9 @@ import popcorn::pop_repos
 import popcorn::pop_json
 
 import commands::commands_http
-import commands::commands_json
-import commands::commands_html
+
+import templates::json_commands
+import templates::html_commands
 
 # Nitweb config file.
 class NitwebConfig
@@ -40,42 +41,10 @@ class NitwebConfig
        var modelbuilder: ModelBuilder
 
        # The JSON API does not filter anything by default.
-       #
-       # So we can cache the model view.
-       var view: ModelView
+       var filter: nullable ModelFilter
 
        # Catalog to pass to handlers.
-       var catalog: Catalog is noinit
-
-       # Build the catalog
-       #
-       # This method should be called at nitweb startup.
-       # TODO move to nitweb
-       fun build_catalog do
-               var catalog = new Catalog(modelbuilder)
-               # Compute the poset
-               for p in view.mpackages do
-                       var g = p.root
-                       assert g != null
-                       modelbuilder.scan_group(g)
-
-                       catalog.deps.add_node(p)
-                       for gg in p.mgroups do for m in gg.mmodules do
-                               for im in m.in_importation.direct_greaters do
-                                       var ip = im.mpackage
-                                       if ip == null or ip == p then continue
-                                       catalog.deps.add_edge(p, ip)
-                               end
-                       end
-               end
-               # Build the catalog
-               for mpackage in view.mpackages do
-                       catalog.package_page(mpackage)
-                       catalog.git_info(mpackage)
-                       catalog.mpackage_stats(mpackage)
-               end
-               self.catalog = catalog
-       end
+       var catalog: Catalog
 end
 
 # Specific handler for the nitweb API.
@@ -86,11 +55,13 @@ abstract class APIHandler
        var config: NitwebConfig
 
        # Find the MEntity ` with `full_name`.
-       fun find_mentity(model: ModelView, full_name: nullable String): nullable MEntity do
+       fun find_mentity(full_name: nullable String): nullable MEntity do
                if full_name == null then return null
-               var mentity = model.mentity_by_full_name(full_name.from_percent_encoding)
+               var mentity = config.model.mentity_by_full_name(full_name.from_percent_encoding, config.filter)
                if mentity == null then return null
-               if config.view.accept_mentity(mentity) then return mentity
+
+               var filter = config.filter
+               if filter == null or filter.accept_mentity(mentity) then return mentity
                return null
        end
 
@@ -105,7 +76,7 @@ abstract class APIHandler
                        res.api_error(400, "Expected mentity full name")
                        return null
                end
-               var mentity = find_mentity(config.view, id)
+               var mentity = find_mentity(id)
                if mentity == null then
                        res.api_error(404, "MEntity `{id}` not found")
                end
@@ -255,6 +226,10 @@ redef class MVirtualType
        redef var api_url = mproperty.api_url is lazy
 end
 
+redef class HtmlightVisitor
+       redef fun hrefto(mentity) do return mentity.html_url
+end
+
 redef class CmdLicenseFile
        redef var file_url is lazy do
                var mentity = self.mentity
index 0a23542..fdbb8db 100644 (file)
@@ -21,9 +21,9 @@ import commands::commands_docdown
 redef class NitwebConfig
        # Specific Markdown processor to use within Nitweb
        var md_processor: MarkdownProcessor is lazy do
-               var parser = new CommandParser(view, modelbuilder)
+               var parser = new CommandParser(model, mainmodule, modelbuilder, catalog)
                var proc = new CmdMarkdownProcessor(parser)
-               proc.decorator = new CmdDecorator(view)
+               proc.decorator = new CmdDecorator(model)
                return proc
        end
 end
index 4fcdb9e..2224150 100644 (file)
@@ -29,38 +29,38 @@ class APIStructuralMetrics
 
        private fun mclasses_metrics: MetricSet do
                var metrics = new MetricSet
-               metrics.register(new CNOA(config.view))
-               metrics.register(new CNOP(config.view))
-               metrics.register(new CNOC(config.view))
-               metrics.register(new CNOD(config.view))
-               metrics.register(new CNOAC(config.view))
-               metrics.register(new CNOAA(config.view))
-               metrics.register(new CNOAI(config.view))
-               metrics.register(new CDIT(config.view))
-               metrics.register(new CNBP(config.view))
-               metrics.register(new CNBA(config.view))
-               metrics.register(new CNBM(config.view))
-               metrics.register(new CNBI(config.view))
-               metrics.register(new CNBV(config.view))
-               metrics.register(new CNBIP(config.view))
-               metrics.register(new CNBRP(config.view))
-               metrics.register(new CNBHP(config.view))
-               metrics.register(new CNBLP(config.view))
+               metrics.register(new CNOA(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOP(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOC(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOD(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOAC(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOAA(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNOAI(config.model, config.mainmodule, config.filter))
+               metrics.register(new CDIT(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBP(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBA(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBM(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBI(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBV(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBIP(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBRP(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBHP(config.model, config.mainmodule, config.filter))
+               metrics.register(new CNBLP(config.model, config.mainmodule, config.filter))
                return metrics
        end
 
        private fun mmodules_metrics: MetricSet do
                var metrics = new MetricSet
-               metrics.register(new MNOA(config.view))
-               metrics.register(new MNOP(config.view))
-               metrics.register(new MNOC(config.view))
-               metrics.register(new MNOD(config.view))
-               metrics.register(new MDIT(config.view))
-               metrics.register(new MNBD(config.view))
-               metrics.register(new MNBI(config.view))
-               metrics.register(new MNBR(config.view))
-               metrics.register(new MNBCC(config.view))
-               metrics.register(new MNBAC(config.view))
+               metrics.register(new MNOA(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNOP(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNOC(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNOD(config.model, config.mainmodule, config.filter))
+               metrics.register(new MDIT(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNBD(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNBI(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNBR(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNBCC(config.model, config.mainmodule, config.filter))
+               metrics.register(new MNBAC(config.model, config.mainmodule, config.filter))
                return metrics
        end
 
index 5c92817..39d4305 100644 (file)
@@ -89,7 +89,7 @@ end
 class APIList
        super APICommand
 
-       redef fun command do return new CmdModelEntities(config.view)
+       redef fun command do return new CmdModelEntities(config.model)
 end
 
 # Return a random list of MEntities.
@@ -98,7 +98,7 @@ end
 class APIRandom
        super APICommand
 
-       redef fun command do return new CmdRandomEntities(config.view)
+       redef fun command do return new CmdRandomEntities(config.model)
 end
 
 # Search mentities from a cmd string.
@@ -107,7 +107,7 @@ end
 class APISearch
        super APIList
 
-       redef fun command do return new CmdCatalogSearch(config.view, config.catalog)
+       redef fun command do return new CmdCatalogSearch(config.model, config.catalog)
 end
 
 # CmdEntity
@@ -118,7 +118,7 @@ end
 class APIEntity
        super APICommand
 
-       redef fun command do return new CmdEntity(config.view)
+       redef fun command do return new CmdEntity(config.model)
 end
 
 # Return the full MDoc of a MEntity.
@@ -127,7 +127,7 @@ end
 class APIEntityDoc
        super APICommand
 
-       redef fun command do return new CmdComment(config.view)
+       redef fun command do return new CmdComment(config.model)
 end
 
 # List MEntity ancestors
@@ -136,7 +136,7 @@ end
 class APIEntityAncestors
        super APICommand
 
-       redef fun command do return new CmdAncestors(config.view)
+       redef fun command do return new CmdAncestors(config.model, config.mainmodule)
 end
 
 # List MEntity parents
@@ -145,7 +145,7 @@ end
 class APIEntityParents
        super APICommand
 
-       redef fun command do return new CmdParents(config.view)
+       redef fun command do return new CmdParents(config.model, config.mainmodule)
 end
 
 # List MEntity children
@@ -154,7 +154,7 @@ end
 class APIEntityChildren
        super APICommand
 
-       redef fun command do return new CmdChildren(config.view)
+       redef fun command do return new CmdChildren(config.model, config.mainmodule)
 end
 
 # List MEntity descendants
@@ -163,7 +163,7 @@ end
 class APIEntityDescendants
        super APICommand
 
-       redef fun command do return new CmdDescendants(config.view)
+       redef fun command do return new CmdDescendants(config.model, config.mainmodule)
 end
 
 # Linearize super definitions of a MClassDef or a MPropDef if any.
@@ -172,7 +172,7 @@ end
 class APIEntityLinearization
        super APICommand
 
-       redef fun command do return new CmdLinearization(config.view)
+       redef fun command do return new CmdLinearization(config.model, config.mainmodule)
 end
 
 # List definitions of a MEntity.
@@ -181,7 +181,7 @@ end
 class APIEntityDefs
        super APICommand
 
-       redef fun command do return new CmdFeatures(config.view)
+       redef fun command do return new CmdFeatures(config.model)
 end
 
 # List intro definitions of a MEntity.
@@ -190,7 +190,7 @@ end
 class APIEntityIntros
        super APICommand
 
-       redef fun command do return new CmdIntros(config.view)
+       redef fun command do return new CmdIntros(config.model, config.mainmodule)
 end
 
 # List redef definitions of a MEntity.
@@ -199,7 +199,7 @@ end
 class APIEntityRedefs
        super APICommand
 
-       redef fun command do return new CmdRedefs(config.view)
+       redef fun command do return new CmdRedefs(config.model, config.mainmodule)
 end
 
 # List all definitions accessible from a MEntity.
@@ -208,7 +208,7 @@ end
 class APIEntityAll
        super APICommand
 
-       redef fun command do return new CmdAllProps(config.view)
+       redef fun command do return new CmdAllProps(config.model, config.mainmodule)
 end
 
 # Return the source code of MEntity.
@@ -217,7 +217,7 @@ end
 class APIEntityCode
        super APICommand
 
-       redef fun command do return new CmdEntityCode(config.view, config.modelbuilder)
+       redef fun command do return new CmdEntityCode(config.model, config.modelbuilder)
 end
 
 # Return the UML diagram for MEntity.
@@ -226,7 +226,7 @@ end
 class APIEntityUML
        super APICommand
 
-       redef fun command do return new CmdUML(config.view)
+       redef fun command do return new CmdUML(config.model, config.mainmodule)
 end
 
 # Return the inheritance graph for MEntity.
@@ -235,7 +235,7 @@ end
 class APIInheritanceGraph
        super APICommand
 
-       redef fun command do return new CmdInheritanceGraph(config.view)
+       redef fun command do return new CmdInheritanceGraph(config.model, config.mainmodule)
 end
 
 # CmdCatalog
@@ -246,7 +246,7 @@ end
 class APICatalogPackages
        super APICommand
 
-       redef fun command do return new CmdCatalogPackages(config.view, config.catalog)
+       redef fun command do return new CmdCatalogPackages(config.model, config.catalog)
 end
 
 # Get the catalog statistics
@@ -255,7 +255,7 @@ end
 class APICatalogStats
        super APICommand
 
-       redef fun command do return new CmdCatalogStats(config.view, config.catalog)
+       redef fun command do return new CmdCatalogStats(config.model, config.catalog)
 end
 
 # Get the package metadata
@@ -264,7 +264,7 @@ end
 class APIEntityMetadata
        super APICommand
 
-       redef fun command do return new CmdMetadata(config.view)
+       redef fun command do return new CmdMetadata(config.model)
 end
 
 # Get all the tags from the catalog
@@ -273,7 +273,7 @@ end
 class APICatalogTags
        super APICommand
 
-       redef fun command do return new CmdCatalogTags(config.view, config.catalog)
+       redef fun command do return new CmdCatalogTags(config.model, config.catalog)
 end
 
 # Get the packages related to a tag
@@ -282,7 +282,7 @@ end
 class APICatalogTag
        super APICommand
 
-       redef fun command do return new CmdCatalogTag(config.view, config.catalog)
+       redef fun command do return new CmdCatalogTag(config.model, config.catalog)
 end
 
 # Get a person existing in the catalog
@@ -291,7 +291,7 @@ end
 class APICatalogPerson
        super APICommand
 
-       redef fun command do return new CmdCatalogPerson(config.view, config.catalog)
+       redef fun command do return new CmdCatalogPerson(config.model, config.catalog)
 end
 
 # Get the list of mpackages maintained by a person
@@ -300,7 +300,7 @@ end
 class APICatalogMaintaining
        super APICommand
 
-       redef fun command do return new CmdCatalogMaintaining(config.view, config.catalog)
+       redef fun command do return new CmdCatalogMaintaining(config.model, config.catalog)
 end
 
 # Get the list of mpackages contributed by a person
@@ -309,7 +309,7 @@ end
 class APICatalogContributing
        super APICommand
 
-       redef fun command do return new CmdCatalogContributing(config.view, config.catalog)
+       redef fun command do return new CmdCatalogContributing(config.model, config.catalog)
 end
 
 # CmdIni
@@ -320,7 +320,7 @@ end
 class APIIniDesc
        super APICommand
 
-       redef fun command do return new CmdIniDescription(config.view)
+       redef fun command do return new CmdIniDescription(config.model)
 end
 
 # Get the package Git URL from the ini file
@@ -329,7 +329,7 @@ end
 class APIIniGit
        super APICommand
 
-       redef fun command do return new CmdIniGitUrl(config.view)
+       redef fun command do return new CmdIniGitUrl(config.model)
 end
 
 # Get the package Git clone command from the ini file
@@ -338,7 +338,7 @@ end
 class APIIniClone
        super APICommand
 
-       redef fun command do return new CmdIniCloneCommand(config.view)
+       redef fun command do return new CmdIniCloneCommand(config.model)
 end
 
 # Get the package issues URL from the ini file
@@ -347,7 +347,7 @@ end
 class APIIniIssues
        super APICommand
 
-       redef fun command do return new CmdIniIssuesUrl(config.view)
+       redef fun command do return new CmdIniIssuesUrl(config.model)
 end
 
 # Get the package maintainer from the ini file
@@ -356,7 +356,7 @@ end
 class APIIniMaintainer
        super APICommand
 
-       redef fun command do return new CmdIniMaintainer(config.view)
+       redef fun command do return new CmdIniMaintainer(config.model)
 end
 
 # Get the package contributors from the ini file
@@ -365,7 +365,7 @@ end
 class APIIniContributors
        super APICommand
 
-       redef fun command do return new CmdIniContributors(config.view)
+       redef fun command do return new CmdIniContributors(config.model)
 end
 
 # Get the package license from the ini file
@@ -374,7 +374,7 @@ end
 class APIIniLicense
        super APICommand
 
-       redef fun command do return new CmdIniLicense(config.view)
+       redef fun command do return new CmdIniLicense(config.model)
 end
 
 # Get the package license file
@@ -383,7 +383,7 @@ end
 class APIIniLicenseFile
        super APICommand
 
-       redef fun command do return new CmdLicenseFile(config.view)
+       redef fun command do return new CmdLicenseFile(config.model)
 end
 
 # Get the package contrib file
@@ -392,7 +392,7 @@ end
 class APIIniContribFile
        super APICommand
 
-       redef fun command do return new CmdContribFile(config.view)
+       redef fun command do return new CmdContribFile(config.model)
 end
 
 # Get the package license file content
@@ -401,7 +401,7 @@ end
 class APIIniLicenseFileContent
        super APICommand
 
-       redef fun command do return new CmdLicenseFileContent(config.view)
+       redef fun command do return new CmdLicenseFileContent(config.model)
 end
 
 # Get the package contrib file content
@@ -410,5 +410,5 @@ end
 class APIIniContribFileContent
        super APICommand
 
-       redef fun command do return new CmdContribFileContent(config.view)
+       redef fun command do return new CmdContribFileContent(config.model)
 end
index 4a94208..bde3f8e 100644 (file)
 module commands_base
 
 import model::model_index
-import catalog
 
 # Documentation command
 #
-# An abstract command that works on a ModelView.
+# An abstract command that works on a Model.
 #
 # Since they are used by a wide variety of clients, initialization of DocCommands
 # works in two steps.
@@ -53,10 +52,11 @@ import catalog
 # See `init_command` for more details about the returned statuses.
 abstract class DocCommand
 
-       # ModelView
-       #
-       # Set of entities and filters used to retrieve data from the model.
-       var view: ModelView
+       # Model to retrieve data for
+       var model: Model
+
+       # ModelFilter to apply if any
+       var filter: nullable ModelFilter
 
        # Initialize the command
        #
@@ -69,6 +69,13 @@ abstract class DocCommand
        #
        # Warnings are generally used to distinguish empty list or mdoc from no data at all.
        fun init_command: CmdMessage do return new CmdSuccess
+
+       # Return a new filter for that command execution.
+       fun cmd_filter: ModelFilter do
+               var filter = self.filter
+               if filter == null then return new ModelFilter
+               return new ModelFilter.from(filter)
+       end
 end
 
 # Command message
@@ -140,11 +147,11 @@ class CmdEntity
                var mentity_name = self.mentity_name
                if mentity_name == null or mentity_name.is_empty then return new ErrorMEntityNoName
 
-               mentity = view.mentity_by_full_name(mentity_name)
+               mentity = model.mentity_by_full_name(mentity_name)
                if mentity == null then
-                       var mentities = view.mentities_by_name(mentity_name)
+                       var mentities = model.mentities_by_name(mentity_name)
                        if mentities.is_empty then
-                               var suggest = view.find(mentity_name, 3)
+                               var suggest = model.find(mentity_name, 3)
                                return new ErrorMEntityNotFound(mentity_name, suggest)
                        else if mentities.length > 1 then
                                return new ErrorMEntityConflict(mentity_name, mentities)
@@ -312,7 +319,7 @@ abstract class CmdEntityList
        super CmdEntity
        super CmdEntities
 
-       autoinit(view, mentity, mentity_name, limit, page, count, max)
+       autoinit(model, filter, mentity, mentity_name, limit, page, count, max)
 
        redef fun init_command do
                var res = init_mentity
index be823d0..f7bce8e 100644 (file)
 module commands_catalog
 
 import commands_model
+import catalog
 
 # A DocCommand based on a Catalog
 abstract class CmdCatalog
        super DocCommand
 
+       autoinit(model, catalog, filter)
+
        # Catalog to query at
        var catalog: Catalog
 end
@@ -30,7 +33,7 @@ class CmdCatalogSearch
        super CmdCatalog
        super CmdSearch
 
-       autoinit(view, catalog, query, limit, page, count, max)
+       autoinit(model, catalog, filter, query, limit, page, count, max)
 
        redef fun init_results do
                if results != null then return new CmdSuccess
@@ -42,10 +45,11 @@ class CmdCatalogSearch
                if query == null then return new ErrorNoQuery
                sorter = null
 
-               var index = view.index
+               var filter = self.filter
+               var index = model.index
 
                # lookup by name prefix
-               var matches = index.find_by_name_prefix(query).uniq.
+               var matches = index.find_by_name_prefix(query, filter).uniq.
                        sort(lname_sorter, name_sorter, kind_sorter)
                matches = matches.rerank.sort(vis_sorter, score_sorter)
 
@@ -53,6 +57,7 @@ class CmdCatalogSearch
                var malus = matches.length
                if catalog.tag2proj.has_key(query) then
                        for mpackage in catalog.tag2proj[query] do
+                               if filter != null and not filter.accept_mentity(mpackage) then continue
                                matches.add new IndexMatch(mpackage, malus)
                                malus += 1
                        end
@@ -62,7 +67,7 @@ class CmdCatalogSearch
                # lookup by full_name prefix
                malus = matches.length
                var full_matches = new IndexMatches
-               for match in index.find_by_full_name_prefix(query).
+               for match in index.find_by_full_name_prefix(query, filter).
                        sort(lfname_sorter, fname_sorter) do
                        match.score += 1
                        full_matches.add match
@@ -72,7 +77,7 @@ class CmdCatalogSearch
                # lookup by similarity
                malus = matches.length
                var sim_matches = new IndexMatches
-               for match in index.find_by_similarity(query).sort(score_sorter, lname_sorter, name_sorter) do
+               for match in index.find_by_similarity(query, filter).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
                        if match.score > query.length then break
                        match.score += 1
                        sim_matches.add match
@@ -130,7 +135,7 @@ class CmdCatalogPackages
        super CmdCatalog
        super CmdEntities
 
-       autoinit(view, catalog, limit, page, count, max)
+       autoinit(model, catalog, filter, limit, page, count, max)
 
        redef var sorter = new CatalogScoreSorter(catalog) is lazy
 
@@ -187,7 +192,7 @@ end
 class CmdCatalogTag
        super CmdCatalogPackages
 
-       autoinit(view, catalog, tag, limit, page, count, max)
+       autoinit(model, catalog, filter, tag, limit, page, count, max)
 
        # The tag to retrieve
        var tag: nullable String = null is optional, writable
@@ -285,7 +290,7 @@ class CmdCatalogMaintaining
        super CmdCatalogPerson
        super CmdCatalogPackages
 
-       autoinit(view, catalog, person, person_name, limit, page, count, max)
+       autoinit(model, catalog, filter, person, person_name, limit, page, count, max)
 
        redef fun init_command do return super
 
@@ -306,7 +311,7 @@ class CmdCatalogContributing
        super CmdCatalogPerson
        super CmdCatalogPackages
 
-       autoinit(view, catalog, person, person_name, limit, page, count, max)
+       autoinit(model, catalog, filter, person, person_name, limit, page, count, max)
 
        # Include maintained packages?
        #
index 280985f..ece9dae 100644 (file)
 # Doc down related queries
 module commands_docdown
 
-import commands::commands_parser
-import commands::commands_html
-
-intrude import doc_down
-intrude import markdown::wikilinks
+import templates::md_commands
+import markdown
 
 # Retrieve the MDoc summary
 #
@@ -28,7 +25,7 @@ class CmdSummary
        super CmdComment
 
        # Markdown processor used to parse the headlines
-       var markdown_processor: nullable MarkdownProcessor = null is optional, writable
+       var markdown_processor: MarkdownProcessor is writable
 
        # Resulting summary
        #
@@ -40,12 +37,6 @@ class CmdSummary
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               var markdown_processor = self.markdown_processor
-               if markdown_processor == null then
-                       markdown_processor = new MarkdownProcessor
-                       self.markdown_processor = markdown_processor
-               end
-
                var mdoc = self.mdoc
                if mdoc == null then
                        mdoc = if fallback then mentity.mdoc_or_fallback else mentity.mdoc
@@ -61,100 +52,3 @@ class CmdSummary
                return res
        end
 end
-
-# Custom Markdown processor able to process doc commands
-class CmdDecorator
-       super NitdocDecorator
-
-       redef type PROCESSOR: CmdMarkdownProcessor
-
-       # View used by wikilink commands to find model entities
-       var view: ModelView
-
-       redef fun add_span_code(v, buffer, from, to) do
-               var text = new FlatBuffer
-               buffer.read(text, from, to)
-               var name = text.write_to_string
-               name = name.replace("nullable ", "")
-               var mentity = try_find_mentity(view, name)
-               if mentity == null then
-                       super
-               else
-                       v.add "<code>"
-                       v.emit_text mentity.html_link.write_to_string
-                       v.add "</code>"
-               end
-       end
-
-       private fun try_find_mentity(view: ModelView, text: String): nullable MEntity do
-               var mentity = view.mentity_by_full_name(text)
-               if mentity != null then return mentity
-
-               var mentities = view.mentities_by_name(text)
-               if mentities.is_empty then
-                       return null
-               else if mentities.length > 1 then
-                       # TODO smart resolve conflicts
-               end
-               return mentities.first
-       end
-
-       redef fun add_wikilink(v, token) do
-               v.render_wikilink(token, view)
-       end
-end
-
-# Same as `InlineDecorator` but with wikilink commands handling
-class CmdInlineDecorator
-       super InlineDecorator
-
-       redef type PROCESSOR: CmdMarkdownProcessor
-
-       # View used by wikilink commands to find model entities
-       var view: ModelView
-
-       redef fun add_wikilink(v, token) do
-               v.render_wikilink(token, view)
-       end
-end
-
-# Custom MarkdownEmitter for commands
-class CmdMarkdownProcessor
-       super MarkdownProcessor
-
-       # Parser used to process doc commands
-       var parser: CommandParser
-
-       # Render a wikilink
-       fun render_wikilink(token: TokenWikiLink, model: ModelView) do
-               var link = token.link
-               if link == null then return
-               var name = token.name
-               if name != null then link = "{name} | {link}"
-
-               var command = parser.parse(link.write_to_string)
-               var error = parser.error
-
-               if error isa CmdError then
-                       emit_text error.to_html.write_to_string
-                       return
-               end
-               if error isa CmdWarning then
-                       emit_text error.to_html.write_to_string
-               end
-               add command.as(not null).to_html
-       end
-end
-
-redef class Text
-       # Read `self` between `nstart` and `nend` (excluded) and writte chars to `out`.
-       private fun read(out: FlatBuffer, nstart, nend: Int): Int do
-               var pos = nstart
-               while pos < length and pos < nend do
-                       out.add self[pos]
-                       pos += 1
-               end
-               if pos == length then return -1
-               return pos
-       end
-end
index 7cb0f97..bffd6a1 100644 (file)
@@ -26,6 +26,9 @@ import dot
 abstract class CmdGraph
        super DocCommand
 
+       # Mainmodule for linearization
+       var mainmodule: MModule
+
        # Rendering format
        #
        # Default is `dot`.
@@ -91,7 +94,7 @@ class CmdUML
        super CmdEntity
        super CmdGraph
 
-       autoinit(view, mentity, mentity_name, format, uml)
+       autoinit(model, mainmodule, filter, mentity, mentity_name, format, uml)
 
        # UML model to return
        var uml: nullable UMLModel = null is optional, writable
@@ -104,10 +107,8 @@ class CmdUML
                var mentity = self.mentity.as(not null)
 
                if mentity isa MClassDef then mentity = mentity.mclass
-               if mentity isa MClass then
-                       uml = new UMLModel(view, view.mainmodule)
-               else if mentity isa MModule then
-                       uml = new UMLModel(view, view.mainmodule)
+               if mentity isa MClass or mentity isa MModule then
+                       uml = new UMLModel(model, mainmodule, filter)
                else
                        return new WarningNoUML(mentity)
                end
@@ -141,7 +142,7 @@ class CmdInheritanceGraph
        super CmdEntity
        super CmdGraph
 
-       autoinit(view, mentity, mentity_name, pdepth, cdepth, format, graph)
+       autoinit(model, mainmodule, filter, mentity, mentity_name, pdepth, cdepth, format, graph)
 
        # Parents depth to display
        var pdepth: nullable Int = null is optional, writable
@@ -159,7 +160,7 @@ class CmdInheritanceGraph
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               graph = new InheritanceGraph(mentity, view)
+               graph = new InheritanceGraph(mentity, model, mainmodule, filter)
                return res
        end
 
@@ -179,8 +180,14 @@ class InheritanceGraph
        # MEntity at the center of this graph
        var center: MEntity
 
-       # ModelView used to filter graph
-       var view: ModelView
+       # Model used to build graph from
+       var model: Model
+
+       # Mainmodule for class linearization
+       var mainmodule: MModule
+
+       # Filter to apply on model if any
+       var filter: nullable ModelFilter
 
        # Graph generated
        var graph: DotGraph is lazy do
@@ -224,7 +231,7 @@ class InheritanceGraph
                        from_dotdotdot(mentity)
                        return
                end
-               var parents = mentity.collect_parents(view)
+               var parents = mentity.collect_parents(mainmodule, filter)
                if parents.length > 10 then
                        from_dotdotdot(mentity)
                        return
@@ -260,7 +267,7 @@ class InheritanceGraph
                        to_dotdotdot(mentity)
                        return
                end
-               var children = mentity.collect_children(view)
+               var children = mentity.collect_children(mainmodule, filter)
                if children.length > 10 then
                        to_dotdotdot(mentity)
                        return
index 70d2062..c018ad2 100644 (file)
 # To be more generic, param names should be extracted as variables.
 module commands_http
 
-import commands
-import commands::commands_catalog
+import commands_catalog
+import commands_graph
+import commands_ini
+import commands_main
+import commands_usage
+
 import nitcorn::vararg_routes
 
 redef class DocCommand
        # Init the command from an HTTPRequest
-       fun http_init(req: HttpRequest): CmdMessage do return init_command
+       fun http_init(req: HttpRequest): CmdMessage do
+               var filter = cmd_filter
+               var opt_vis = req.visibility_arg("min-visibility")
+               if opt_vis != null then filter.min_visibility = opt_vis
+               var opt_fictive = req.bool_arg("no-fictive")
+               if opt_fictive != null then filter.accept_fictive = not opt_fictive
+               var opt_test = req.bool_arg("no-test")
+               if opt_test != null then filter.accept_test = not opt_test
+               var opt_redef = req.bool_arg("no-redef")
+               if opt_redef != null then filter.accept_redef = not opt_redef
+               var opt_extern = req.bool_arg("no-extern")
+               if opt_extern != null then filter.accept_extern = not opt_extern
+               var opt_example = req.bool_arg("no-example")
+               if opt_example != null then filter.accept_example = not opt_example
+               var opt_attr = req.bool_arg("no-attribute")
+               if opt_attr != null then filter.accept_attribute = not opt_attr
+               var opt_doc = req.bool_arg("no-empty-doc")
+               if opt_doc != null then filter.accept_empty_doc = not opt_doc
+               var opt_inh = req.mentity_arg(model, "inherit")
+               if opt_inh != null then filter.accept_inherited = opt_inh
+               var opt_match = req.string_arg("match")
+               if opt_match != null then filter.accept_full_name = opt_match
+               self.filter = filter
+               return init_command
+       end
 end
 
 redef class CmdEntity
@@ -39,8 +67,10 @@ end
 
 redef class CmdList
        redef fun http_init(req) do
-               limit = req.int_arg("l")
-               page = req.int_arg("p")
+               var opt_limit = req.int_arg("l")
+               if opt_limit != null then limit = opt_limit
+               var opt_page = req.int_arg("p")
+               if opt_page != null then page = opt_page
                return super
        end
 end
@@ -78,31 +108,38 @@ end
 
 redef class CmdComment
        redef fun http_init(req) do
-               full_doc = req.bool_arg("full_doc") or else true
-               fallback = req.bool_arg("fallback") or else true
-               format = req.string_arg("format") or else "raw"
+               var opt_full_doc = req.bool_arg("full_doc")
+               if opt_full_doc != null then full_doc = opt_full_doc
+               var opt_fallback = req.bool_arg("fallback")
+               if opt_fallback != null then fallback = opt_fallback
+               var opt_format = req.string_arg("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
 
 redef class CmdEntityLink
        redef fun http_init(req) do
-               text = req.string_arg("text")
-               title = req.string_arg("title")
+               var opt_text = req.string_arg("text")
+               if opt_text != null then text = opt_text
+               var opt_title = req.string_arg("title")
+               if opt_title != null then title = opt_title
                return super
        end
 end
 
 redef class CmdAncestors
        redef fun http_init(req) do
-               parents = req.bool_arg("parents") or else true
+               var opt_parents = req.bool_arg("parents")
+               if opt_parents != null then parents = opt_parents
                return super
        end
 end
 
 redef class CmdDescendants
        redef fun http_init(req) do
-               children = req.bool_arg("children") or else true
+               var opt_children = req.bool_arg("children")
+               if opt_children != null then children = opt_children
                return super
        end
 end
@@ -121,14 +158,16 @@ end
 
 redef class CmdModelEntities
        redef fun http_init(req) do
-               kind = req.string_arg("kind") or else "all"
+               var opt_kind = req.string_arg("kind")
+               if opt_kind != null then kind = opt_kind
                return super
        end
 end
 
 redef class CmdCode
        redef fun http_init(req) do
-               format = req.string_arg("format") or else "raw"
+               var opt_format = req.string_arg("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
@@ -140,7 +179,8 @@ redef class CmdEntityCode
                if name != null then name = name.from_percent_encoding
                mentity_name = name
 
-               format = req.string_arg("format") or else "raw"
+               var opt_format = req.string_arg("format")
+               if opt_format != null then format = opt_format
                return init_command
        end
 end
@@ -149,15 +189,18 @@ end
 
 redef class CmdGraph
        redef fun http_init(req) do
-               format = req.string_arg("format") or else "dot"
+               var opt_format = req.string_arg("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
 
 redef class CmdInheritanceGraph
        redef fun http_init(req) do
-               pdepth = req.int_arg("pdepth")
-               cdepth = req.int_arg("cdepth")
+               var opt_pdepth = req.int_arg("pdepth")
+               if opt_pdepth != null then pdepth = opt_pdepth
+               var opt_cdepth = req.int_arg("cdepth")
+               if opt_cdepth != null then cdepth = opt_cdepth
                return super
        end
 end
@@ -181,3 +224,44 @@ redef class CmdCatalogPerson
                return super
        end
 end
+
+# Util
+
+redef class HttpRequest
+
+       # Map String visiblity name to MVisibility object
+       var allowed_visibility: HashMap[String, MVisibility] is lazy do
+               var res = new HashMap[String, MVisibility]
+               res["public"] = public_visibility
+               res["protected"] = protected_visibility
+               res["private"] = private_visibility
+               return res
+       end
+
+       # Get arg as a MVisibility
+       #
+       # Return `null` if no option with that `key` or if the value is not in
+       # `allowed_visibility`.
+       fun visibility_arg(key: String): nullable MVisibility do
+               var value = string_arg(key)
+               if value == null then return null
+               if not allowed_visibility.keys.has(key) then return null
+               return allowed_visibility[value]
+       end
+
+       # Get arg as a MEntity
+       #
+       # Lookup first by `MEntity::full_name` then by `MEntity::name`.
+       # Return `null` if the mentity name does not exist or return a conflict.
+       private fun mentity_arg(model: Model, key: String): nullable MEntity do
+               var value = string_arg(key)
+               if value == null or value.is_empty then return null
+
+               var mentity = model.mentity_by_full_name(value)
+               if mentity != null then return mentity
+
+               var mentities = model.mentities_by_name(value)
+               if mentities.is_empty or mentities.length > 1 then return null
+               return mentities.first
+       end
+end
index 9274fd0..df312c4 100644 (file)
@@ -14,7 +14,7 @@
 
 module commands_ini
 
-import doc::commands::commands_model
+import commands_model
 
 # Cmd that finds the ini file related to an `mentity`
 abstract class CmdIni
index 851b79e..2b3e861 100644 (file)
@@ -14,7 +14,7 @@
 
 module commands_main
 
-import doc::commands::commands_model
+import commands_model
 
 # Cmd that finds the mains of an `mentity`
 class CmdMains
@@ -29,11 +29,11 @@ class CmdMains
                var mentities = new Array[MEntity]
 
                if mentity isa MPackage then
-                       for mmodule in mentity.collect_all_mmodules(view) do
+                       for mmodule in mentity.collect_all_mmodules(filter) do
                                if mmodule_has_main(mmodule) then mentities.add mmodule
                        end
                else if mentity isa MGroup then
-                       for mmodule in mentity.collect_all_mmodules(view) do
+                       for mmodule in mentity.collect_all_mmodules(filter) do
                                if mmodule_has_main(mmodule) then mentities.add mmodule
                        end
                else if mentity isa MModule then
@@ -50,9 +50,9 @@ class CmdMains
 
        # Does `mmodule` has a `main` method?
        private fun mmodule_has_main(mmodule: MModule): Bool do
-               for mclassdef in mmodule.collect_redef_mclassdefs(view) do
+               for mclassdef in mmodule.collect_redef_mclassdefs(filter) do
                        if mclassdef.name != "Sys" then continue
-                       for mpropdef in mclassdef.collect_redef_mpropdefs(view) do
+                       for mpropdef in mclassdef.collect_redef_mpropdefs(filter) do
                                if mpropdef.name == "main" then return true
                        end
                end
@@ -156,12 +156,12 @@ class CmdTesting
                var mentities = new Array[MEntity]
                if not mentity isa MPackage then return new WarningNoTest(mentity)
 
-               for mgroup in mentity.collect_all_mgroups(view) do
+               for mgroup in mentity.collect_all_mgroups(filter) do
                        if mgroup.is_test then
                                mentities.add mgroup
                                continue
                        end
-                       for mmodule in mgroup.collect_mmodules(view) do
+                       for mmodule in mgroup.collect_mmodules(filter) do
                                if mmodule.is_test then mentities.add mmodule
                        end
                end
index a119d45..3a7215b 100644 (file)
 module commands_model
 
 import commands_base
-
-import model::model_collect
 import modelize
-import modelbuilder
-import htmlight
-import doc_down
 
 # Retrieve the MDoc related to a MEntity
 class CmdComment
@@ -47,7 +42,7 @@ class CmdComment
 
        # Format to render the comment
        #
-       # Can be one of `raw` or `html`.
+       # Can be one of `raw`, `html` or `md`.
        # Default is `raw`.
        var format = "raw" is optional, writable
 
@@ -74,10 +69,6 @@ class CmdComment
                var mdoc = self.mdoc
                if mdoc == null then return null
 
-               if format == "html" then
-                       if full_doc then return mdoc.html_documentation
-                       return mdoc.html_synopsis
-               end
                if full_doc then return mdoc.documentation
                return mdoc.synopsis
        end
@@ -121,11 +112,23 @@ class CmdEntityLink
        end
 end
 
+# An abstract inheritance command
+#
+# For things like ancestors, parents, children and descendants.
+abstract class CmdInheritance
+       super CmdEntityList
+
+       autoinit(model, mainmodule, filter, mentity, mentity_name, limit, page, count, max)
+
+       # Mainmodule for class linearization
+       var mainmodule: MModule
+end
+
 # MEntity ancestors command
 #
 # Retrieve all the ancestors (direct and indirect) of a MEntity.
 class CmdAncestors
-       super CmdEntityList
+       super CmdInheritance
 
        # Include direct parents in the ancestors list
        #
@@ -139,13 +142,13 @@ class CmdAncestors
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               var ancestors = mentity.collect_ancestors(view).to_a
+               var ancestors = mentity.collect_ancestors(mainmodule, filter).to_a
                if parents then
                        results = ancestors
                        return res
                end
 
-               var parents = mentity.collect_parents(view)
+               var parents = mentity.collect_parents(mainmodule, filter)
                var mentities = new HashSet[MEntity]
                for ancestor in ancestors do
                        if not parents.has(ancestor) then mentities.add ancestor
@@ -157,7 +160,7 @@ end
 
 # MEntity parents command
 class CmdParents
-       super CmdEntityList
+       super CmdInheritance
 
        redef fun init_results do
                if results != null then return new CmdSuccess
@@ -166,14 +169,14 @@ class CmdParents
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               results = mentity.collect_parents(view).to_a
+               results = mentity.collect_parents(mainmodule, filter).to_a
                return res
        end
 end
 
 # MEntity children command
 class CmdChildren
-       super CmdEntityList
+       super CmdInheritance
 
        redef fun init_results do
                if results != null then return new CmdSuccess
@@ -182,14 +185,14 @@ class CmdChildren
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               results = mentity.collect_children(view).to_a
+               results = mentity.collect_children(mainmodule, filter).to_a
                return res
        end
 end
 
 # MEntity descendants command
 class CmdDescendants
-       super CmdEntityList
+       super CmdInheritance
 
        # Include direct children in the descendants list
        #
@@ -203,13 +206,13 @@ class CmdDescendants
                if not res isa CmdSuccess then return res
                var mentity = self.mentity.as(not null)
 
-               var descendants = mentity.collect_descendants(view).to_a
+               var descendants = mentity.collect_descendants(mainmodule, filter).to_a
                if children then
                        results = descendants
                        return res
                end
 
-               var children = mentity.collect_children(view)
+               var children = mentity.collect_children(mainmodule, filter)
                var mentities = new HashSet[MEntity]
                for descendant in descendants do
                        if not children.has(descendant) then mentities.add descendant
@@ -223,7 +226,7 @@ end
 #
 # Collects and linearizes definitions about an MEntity.
 class CmdLinearization
-       super CmdEntityList
+       super CmdInheritance
 
        # Same states than `CmdEntity::init_mentity`
        #
@@ -237,7 +240,7 @@ class CmdLinearization
                var mentity = self.mentity.as(not null)
 
                sorter = null
-               results = mentity.collect_linearization(view.mainmodule)
+               results = mentity.collect_linearization(mainmodule)
                if results == null then return new WarningNoLinearization(mentity)
                return res
        end
@@ -272,7 +275,7 @@ class CmdSearch
                var query = self.query
                if query == null then return new ErrorNoQuery
                sorter = null
-               results = view.find(query)
+               results = model.find(query)
                return res
        end
 end
@@ -302,21 +305,21 @@ class CmdFeatures
 
                var mentities = new Array[MEntity]
                if mentity isa MPackage then
-                       mentities.add_all mentity.collect_mgroups(view)
-                       mentities.add_all mentity.collect_mmodules(view)
+                       mentities.add_all mentity.collect_mgroups(filter)
+                       mentities.add_all mentity.collect_mmodules(filter)
                else if mentity isa MGroup then
-                       mentities.add_all mentity.collect_mgroups(view)
-                       mentities.add_all mentity.collect_mmodules(view)
+                       mentities.add_all mentity.collect_mgroups(filter)
+                       mentities.add_all mentity.collect_mmodules(filter)
                else if mentity isa MModule then
-                       mentities.add_all mentity.collect_local_mclassdefs(view)
+                       mentities.add_all mentity.collect_local_mclassdefs(filter)
                else if mentity isa MClass then
-                       mentities.add_all mentity.collect_intro_mproperties(view)
-                       mentities.add_all mentity.collect_redef_mpropdefs(view)
+                       mentities.add_all mentity.collect_intro_mproperties(filter)
+                       mentities.add_all mentity.collect_redef_mpropdefs(filter)
                else if mentity isa MClassDef then
-                       mentities.add_all mentity.collect_intro_mpropdefs(view)
-                       mentities.add_all mentity.collect_redef_mpropdefs(view)
+                       mentities.add_all mentity.collect_intro_mpropdefs(filter)
+                       mentities.add_all mentity.collect_redef_mpropdefs(filter)
                else if mentity isa MProperty then
-                       mentities.add_all mentity.collect_mpropdefs(view)
+                       mentities.add_all mentity.collect_mpropdefs(filter)
                else
                        return new WarningNoFeatures(mentity)
                end
@@ -327,7 +330,7 @@ end
 
 # TODO remove once the filters/sorters are merged
 class CmdIntros
-       super CmdEntityList
+       super CmdInheritance
 
        redef fun init_results do
                if results != null then return new CmdSuccess
@@ -337,14 +340,14 @@ class CmdIntros
                var mentity = self.mentity.as(not null)
 
                if mentity isa MModule then
-                       var mentities = mentity.collect_intro_mclasses(view).to_a
+                       var mentities = mentity.collect_intro_mclasses(filter).to_a
                        self.results = mentities
                else if mentity isa MClass then
-                       var mentities = mentity.collect_intro_mproperties(view).to_a
+                       var mentities = mentity.collect_intro_mproperties(filter).to_a
                        self.results = mentities
                else if mentity isa MClassDef then
-                       var mentities = mentity.collect_intro_mpropdefs(view).to_a
-                       view.mainmodule.linearize_mpropdefs(mentities)
+                       var mentities = mentity.collect_intro_mpropdefs(filter).to_a
+                       mainmodule.linearize_mpropdefs(mentities)
                        self.results = mentities
                else
                        return new WarningNoFeatures(mentity)
@@ -355,9 +358,9 @@ end
 
 # TODO remove once the filters/sorters are merged
 class CmdRedefs
-       super CmdEntityList
+       super CmdInheritance
 
-       redef fun init_command do
+       redef fun init_results do
                if results != null then return new CmdSuccess
 
                var res = super
@@ -365,14 +368,14 @@ class CmdRedefs
                var mentity = self.mentity.as(not null)
 
                if mentity isa MModule then
-                       var mentities = mentity.collect_redef_mclasses(view).to_a
+                       var mentities = mentity.collect_redef_mclassdefs(filter).to_a
                        self.results = mentities
                else if mentity isa MClass then
-                       var mentities = mentity.collect_redef_mproperties(view).to_a
+                       var mentities = mentity.collect_redef_mpropdefs(filter).to_a
                        self.results = mentities
                else if mentity isa MClassDef then
-                       var mentities = mentity.collect_redef_mpropdefs(view).to_a
-                       view.mainmodule.linearize_mpropdefs(mentities)
+                       var mentities = mentity.collect_redef_mpropdefs(filter).to_a
+                       mainmodule.linearize_mpropdefs(mentities)
                        self.results = mentities
                else
                        return new WarningNoFeatures(mentity)
@@ -383,7 +386,7 @@ end
 
 # TODO remove once the filters/sorters are merged
 class CmdAllProps
-       super CmdEntityList
+       super CmdInheritance
 
        redef fun init_results do
                if results != null then return new CmdSuccess
@@ -393,7 +396,7 @@ class CmdAllProps
                var mentity = self.mentity.as(not null)
 
                if mentity isa MClass then
-                       results = mentity.collect_accessible_mproperties(view).to_a
+                       results = mentity.collect_accessible_mproperties(mainmodule, filter).to_a
                else
                        return new WarningNoFeatures(mentity)
                end
@@ -415,10 +418,10 @@ end
 abstract class CmdCode
        super DocCommand
 
-       autoinit(view, modelbuilder, format)
+       autoinit(model, filter, node, format)
 
-       # ModelBuilder used to get AST nodes
-       var modelbuilder: ModelBuilder
+       # AST node to display code from
+       var node: nullable ANode = null is optional, writable
 
        # Rendering format
        #
@@ -432,17 +435,7 @@ abstract class CmdCode
        var format = "raw" is optional, writable
 
        # Render `node` depending on the selected `format`
-       fun render_code(node: nullable ANode): nullable Writable do
-               if node == null then return null
-               if format == "html" then
-                       var hl = new HtmlightVisitor
-                       hl.highlight_node node
-                       return hl.html
-               else if format == "ansi" then
-                       var hl = new AnsiHighlightVisitor
-                       hl.highlight_node node
-                       return hl.result
-               end
+       fun render_code(node: ANode): Writable do
                return node.location.text
        end
 end
@@ -452,10 +445,10 @@ class CmdEntityCode
        super CmdEntity
        super CmdCode
 
-       autoinit(view, modelbuilder, mentity, mentity_name, format)
+       autoinit(model, modelbuilder, filter, mentity, mentity_name, format)
 
-       # AST node to return
-       var node: nullable ANode = null is optional, writable
+       # ModelBuilder used to get AST nodes from entities
+       var modelbuilder: ModelBuilder
 
        # Same as `CmdEntity::init_mentity`
        #
@@ -510,21 +503,21 @@ class CmdModelEntities
 
                var mentities = new Array[MEntity]
                if kind == "packages" then
-                       mentities = view.mpackages.to_a
+                       mentities = model.collect_mpackages(filter).to_a
                else if kind == "groups" then
-                       mentities = view.mgroups.to_a
+                       mentities = model.collect_mgroups(filter).to_a
                else if kind == "modules" then
-                       mentities = view.mmodules.to_a
+                       mentities = model.collect_mmodules(filter).to_a
                else if kind == "classes" then
-                       mentities = view.mclasses.to_a
+                       mentities = model.collect_mclasses(filter).to_a
                else if kind == "classdefs" then
-                       mentities = view.mclassdefs.to_a
+                       mentities = model.collect_mclassdefs(filter).to_a
                else if kind == "properties" then
-                       mentities = view.mproperties.to_a
+                       mentities = model.collect_mproperties(filter).to_a
                else if kind == "propdefs" then
-                       mentities = view.mpropdefs.to_a
+                       mentities = model.collect_mpropdefs(filter).to_a
                else
-                       mentities = view.mentities.to_a
+                       mentities = model.collect_mentities(filter).to_a
                end
                results = mentities
                return res
index 77fdd25..52ec92b 100644 (file)
 # Used by both Nitx and the Markdown doc commands.
 module commands_parser
 
-import commands::commands_model
-import commands::commands_graph
-import commands::commands_usage
-import commands::commands_catalog
-import commands::commands_ini
-import commands::commands_main
+import commands_catalog
+import commands_graph
+import commands_ini
+import commands_main
+import commands_usage
 
 # Parse string commands to create DocQueries
 class CommandParser
 
-       # ModelView used to retrieve mentities
-       var view: ModelView
+       # Model used to retrieve mentities
+       var model: Model
+
+       # Main module for linearization
+       var mainmodule: MModule
 
        # ModelBuilder used to retrieve AST nodes
        var modelbuilder: ModelBuilder
@@ -137,7 +139,7 @@ class CommandParser
                end
 
                # Parse command options
-               var opts = new HashMap[String, String]
+               var opts = new CmdOptions
                while pos < string.length do
                        # Parse option name
                        tmp.clear
@@ -157,7 +159,7 @@ class CommandParser
                # Build the command
                var command
                if is_short_link then
-                       command = new CmdEntityLink(view)
+                       command = new CmdEntityLink(model)
                else
                        command = new_command(name)
                end
@@ -178,56 +180,56 @@ class CommandParser
        # You must redefine this method to add new custom commands.
        fun new_command(name: String): nullable DocCommand do
                # CmdEntity
-               if name == "link" then return new CmdEntityLink(view)
-               if name == "doc" then return new CmdComment(view)
-               if name == "code" then return new CmdEntityCode(view, modelbuilder)
-               if name == "lin" then return new CmdLinearization(view)
-               if name == "defs" then return new CmdFeatures(view)
-               if name == "parents" then return new CmdParents(view)
-               if name == "ancestors" then return new CmdAncestors(view)
-               if name == "children" then return new CmdChildren(view)
-               if name == "descendants" then return new CmdDescendants(view)
-               if name == "param" then return new CmdParam(view)
-               if name == "return" then return new CmdReturn(view)
-               if name == "new" then return new CmdNew(view, modelbuilder)
-               if name == "call" then return new CmdCall(view, modelbuilder)
+               if name == "link" then return new CmdEntityLink(model)
+               if name == "doc" then return new CmdComment(model)
+               if name == "code" then return new CmdEntityCode(model, modelbuilder)
+               if name == "lin" then return new CmdLinearization(model, mainmodule)
+               if name == "defs" then return new CmdFeatures(model)
+               if name == "parents" then return new CmdParents(model, mainmodule)
+               if name == "ancestors" then return new CmdAncestors(model, mainmodule)
+               if name == "children" then return new CmdChildren(model, mainmodule)
+               if name == "descendants" then return new CmdDescendants(model, mainmodule)
+               if name == "param" then return new CmdParam(model)
+               if name == "return" then return new CmdReturn(model)
+               if name == "new" then return new CmdNew(model, modelbuilder)
+               if name == "call" then return new CmdCall(model, modelbuilder)
                # CmdGraph
-               if name == "uml" then return new CmdUML(view)
-               if name == "graph" then return new CmdInheritanceGraph(view)
+               if name == "uml" then return new CmdUML(model, mainmodule)
+               if name == "graph" then return new CmdInheritanceGraph(model, mainmodule)
                # CmdModel
-               if name == "list" then return new CmdModelEntities(view)
-               if name == "random" then return new CmdRandomEntities(view)
+               if name == "list" then return new CmdModelEntities(model)
+               if name == "random" then return new CmdRandomEntities(model)
                # Ini
-               if name == "ini-desc" then return new CmdIniDescription(view)
-               if name == "ini-git" then return new CmdIniGitUrl(view)
-               if name == "ini-issues" then return new CmdIniIssuesUrl(view)
-               if name == "ini-license" then return new CmdIniLicense(view)
-               if name == "ini-maintainer" then return new CmdIniMaintainer(view)
-               if name == "ini-contributors" then return new CmdIniContributors(view)
-               if name == "license-file" then return new CmdLicenseFile(view)
-               if name == "license-content" then return new CmdLicenseFileContent(view)
-               if name == "contrib-file" then return new CmdContribFile(view)
-               if name == "contrib-content" then return new CmdContribFileContent(view)
-               if name == "git-clone" then return new CmdIniCloneCommand(view)
+               if name == "ini-desc" then return new CmdIniDescription(model)
+               if name == "ini-git" then return new CmdIniGitUrl(model)
+               if name == "ini-issues" then return new CmdIniIssuesUrl(model)
+               if name == "ini-license" then return new CmdIniLicense(model)
+               if name == "ini-maintainer" then return new CmdIniMaintainer(model)
+               if name == "ini-contributors" then return new CmdIniContributors(model)
+               if name == "license-file" then return new CmdLicenseFile(model)
+               if name == "license-content" then return new CmdLicenseFileContent(model)
+               if name == "contrib-file" then return new CmdContribFile(model)
+               if name == "contrib-content" then return new CmdContribFileContent(model)
+               if name == "git-clone" then return new CmdIniCloneCommand(model)
                # CmdMain
-               if name == "mains" then return new CmdMains(view)
-               if name == "main-compile" then return new CmdMainCompile(view)
-               if name == "main-run" then return new CmdManSynopsis(view)
-               if name == "main-opts" then return new CmdManOptions(view)
-               if name == "testing" then return new CmdTesting(view)
+               if name == "mains" then return new CmdMains(model)
+               if name == "main-compile" then return new CmdMainCompile(model)
+               if name == "main-run" then return new CmdManSynopsis(model)
+               if name == "main-opts" then return new CmdManOptions(model)
+               if name == "testing" then return new CmdTesting(model)
                # CmdCatalog
                var catalog = self.catalog
                if catalog != null then
-                       if name == "catalog" then return new CmdCatalogPackages(view, catalog)
-                       if name == "stats" then return new CmdCatalogStats(view, catalog)
-                       if name == "tags" then return new CmdCatalogTags(view, catalog)
-                       if name == "tag" then return new CmdCatalogTag(view, catalog)
-                       if name == "person" then return new CmdCatalogPerson(view, catalog)
-                       if name == "contrib" then return new CmdCatalogContributing(view, catalog)
-                       if name == "maintain" then return new CmdCatalogMaintaining(view, catalog)
-                       if name == "search" then return new CmdCatalogSearch(view, catalog)
+                       if name == "catalog" then return new CmdCatalogPackages(model, catalog)
+                       if name == "stats" then return new CmdCatalogStats(model, catalog)
+                       if name == "tags" then return new CmdCatalogTags(model, catalog)
+                       if name == "tag" then return new CmdCatalogTag(model, catalog)
+                       if name == "person" then return new CmdCatalogPerson(model, catalog)
+                       if name == "contrib" then return new CmdCatalogContributing(model, catalog)
+                       if name == "maintain" then return new CmdCatalogMaintaining(model, catalog)
+                       if name == "search" then return new CmdCatalogSearch(model, catalog)
                else
-                       if name == "search" then return new CmdSearch(view)
+                       if name == "search" then return new CmdSearch(model)
                end
                return null
        end
@@ -252,7 +254,29 @@ end
 redef class DocCommand
 
        # Initialize the command from the CommandParser data
-       fun parser_init(arg: String, options: Map[String, String]): CmdMessage do
+       fun parser_init(arg: String, options: CmdOptions): CmdMessage do
+               var filter = cmd_filter
+               var opt_vis = options.opt_visibility("min-visibility")
+               if opt_vis != null then filter.min_visibility = opt_vis
+               var opt_fictive = options.opt_bool("no-fictive")
+               if opt_fictive != null then filter.accept_fictive = not opt_fictive
+               var opt_test = options.opt_bool("no-test")
+               if opt_test != null then filter.accept_test = not opt_test
+               var opt_redef = options.opt_bool("no-redef")
+               if opt_redef != null then filter.accept_redef = not opt_redef
+               var opt_extern = options.opt_bool("no-extern")
+               if opt_extern != null then filter.accept_extern = not opt_extern
+               var opt_example = options.opt_bool("no-example")
+               if opt_example != null then filter.accept_example = not opt_example
+               var opt_attr = options.opt_bool("no-attribute")
+               if opt_attr != null then filter.accept_attribute = not opt_attr
+               var opt_doc = options.opt_bool("no-empty-doc")
+               if opt_doc != null then filter.accept_empty_doc = not opt_doc
+               var opt_inh = options.opt_mentity(model, "inherit")
+               if opt_inh != null then filter.accept_inherited = opt_inh
+               var opt_match = options.opt_string("match")
+               if opt_match != null then filter.accept_full_name = opt_match
+               self.filter = filter
                return init_command
        end
 end
@@ -266,7 +290,10 @@ end
 
 redef class CmdList
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("limit") and options["limit"].is_int then limit = options["limit"].to_i
+               var opt_page = options.opt_int("page")
+               if opt_page != null then page = opt_page
+               var opt_limit = options.opt_int("limit")
+               if opt_limit != null then limit = opt_limit
                return super
        end
 end
@@ -275,24 +302,30 @@ end
 
 redef class CmdComment
        redef fun parser_init(mentity_name, options) do
-               full_doc = not options.has_key("only-synopsis")
-               fallback = not options.has_key("no-fallback")
-               if options.has_key("format") then format = options["format"]
+               var opt_full_doc = options.opt_bool("only-synopsis")
+               if opt_full_doc != null then full_doc = not opt_full_doc
+               var opt_fallback = options.opt_bool("no-fallback")
+               if opt_fallback != null then fallback = not opt_fallback
+               var opt_format = options.opt_string("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
 
 redef class CmdEntityLink
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("text") then text = options["text"]
-               if options.has_key("title") then title = options["title"]
+               var opt_text = options.opt_string("text")
+               if opt_text != null then text = opt_text
+               var opt_title = options.opt_string("title")
+               if opt_title != null then title = opt_title
                return super
        end
 end
 
 redef class CmdCode
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("format") then format = options["format"]
+               var opt_format = options.opt_string("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
@@ -300,21 +333,22 @@ end
 redef class CmdSearch
        redef fun parser_init(mentity_name, options) do
                query = mentity_name
-               if options.has_key("page") and options["page"].is_int then page = options["page"].to_i
                return super
        end
 end
 
 redef class CmdAncestors
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("parents") and options["parents"] == "false" then parents = false
+               var opt_parents = options.opt_bool("no-parents")
+               if opt_parents != null then parents = not opt_parents
                return super
        end
 end
 
 redef class CmdDescendants
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("children") and options["children"] == "false" then children = false
+               var opt_children = options.opt_bool("no-children")
+               if opt_children != null then children = not opt_children
                return super
        end
 end
@@ -328,19 +362,18 @@ end
 
 redef class CmdGraph
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("format") then format = options["format"]
+               var opt_format = options.opt_string("format")
+               if opt_format != null then format = opt_format
                return super
        end
 end
 
 redef class CmdInheritanceGraph
        redef fun parser_init(mentity_name, options) do
-               if options.has_key("pdepth") and options["pdepth"].is_int then
-                       pdepth = options["pdepth"].to_i
-               end
-               if options.has_key("cdepth") and options["cdepth"].is_int then
-                       cdepth = options["cdepth"].to_i
-               end
+               var opt_pdepth = options.opt_int("pdepth")
+               if opt_pdepth != null then pdepth = opt_pdepth
+               var opt_cdepth = options.opt_int("cdepth")
+               if opt_cdepth != null then cdepth = opt_cdepth
                return super
        end
 end
@@ -363,6 +396,80 @@ end
 
 # Utils
 
+# Commands options
+class CmdOptions
+       super HashMap[String,  String]
+
+       # Map String visiblity name to MVisibility object
+       var allowed_visibility: HashMap[String, MVisibility] is lazy do
+               var res = new HashMap[String, MVisibility]
+               res["public"] = public_visibility
+               res["protected"] = protected_visibility
+               res["private"] = private_visibility
+               return res
+       end
+
+       # Get option value for `key` as String
+       #
+       # Return `null` if no option with that `key` or if value is empty.
+       fun opt_string(key: String): nullable String do
+               if not has_key(key) then return null
+               var value = self[key]
+               if value.is_empty then return null
+               return value
+       end
+
+       # Get option value for `key` as Int
+       #
+       # Return `null` if no option with that `key` or if value is not an Int.
+       fun opt_int(key: String): nullable Int do
+               if not has_key(key) then return null
+               var value = self[key]
+               if not value.is_int then return null
+               return value.to_i
+       end
+
+       # Get option value as bool
+       #
+       # Return `true` if the value with that `key` is empty or equals `"true"`.
+       # Return `false` if the value with that `key` equals `"false"`.
+       # Return `null` in any other case.
+       fun opt_bool(key: String): nullable Bool do
+               if not has_key(key) then return null
+               var value = self[key]
+               if value.is_empty or value == "true" then return true
+               if value == "false" then return false
+               return null
+       end
+
+       # Get option as a MVisibility
+       #
+       # Return `null` if no option with that `key` or if the value is not in
+       # `allowed_visibility`.
+       fun opt_visibility(key: String): nullable MVisibility do
+               var value = opt_string(key)
+               if value == null then return null
+               if not allowed_visibility.keys.has(key) then return null
+               return allowed_visibility[value]
+       end
+
+       # Get option as a MEntity
+       #
+       # Lookup first by `MEntity::full_name` then by `MEntity::name`.
+       # Return `null` if the mentity name does not exist or return a conflict.
+       private fun opt_mentity(model: Model, key: String): nullable MEntity do
+               var value = opt_string(key)
+               if value == null or value.is_empty then return null
+
+               var mentity = model.mentity_by_full_name(value)
+               if mentity != null then return mentity
+
+               var mentities = model.mentities_by_name(value)
+               if mentities.is_empty or mentities.length > 1 then return null
+               return mentities.first
+       end
+end
+
 redef class Text
        # Read `self` as raw text until `nend` and append it to the `out` buffer.
        private fun read_until(out: FlatBuffer, start: Int, nend: Char...): Int do
index 3b4efab..82e26ee 100644 (file)
@@ -35,7 +35,7 @@ class CmdParam
                if not mentity isa MClass then return new ErrorNotClass(mentity)
 
                var mentities = new HashSet[MEntity]
-               for mproperty in view.mproperties do
+               for mproperty in model.collect_mproperties(filter) do
                        if not mproperty isa MMethod then continue
                        var msignature = mproperty.intro.msignature
                        if msignature != null then
@@ -70,7 +70,7 @@ class CmdReturn
                if not mentity isa MClass then return new ErrorNotClass(mentity)
 
                var mentities = new HashSet[MEntity]
-               for mproperty in view.mproperties do
+               for mproperty in model.collect_mproperties(filter) do
                        if not mproperty isa MMethod then continue
                        var msignature = mproperty.intro.msignature
                        if msignature != null then
@@ -93,7 +93,7 @@ end
 class CmdNew
        super CmdEntityList
 
-       autoinit(view, modelbuilder, mentity, mentity_name, limit, page, count, max)
+       autoinit(model, modelbuilder, filter, mentity, mentity_name, limit, page, count, max)
 
        # ModelBuilder used to retrieve AST nodes
        var modelbuilder: ModelBuilder
@@ -109,7 +109,7 @@ class CmdNew
                if not mentity isa MClass then return new ErrorNotClass(mentity)
 
                var mentities = new HashSet[MEntity]
-               for mpropdef in view.mpropdefs do
+               for mpropdef in model.collect_mpropdefs(filter) do
                        var visitor = new TypeInitVisitor(mentity)
                        var npropdef = modelbuilder.mpropdef2node(mpropdef)
                        if npropdef == null then continue
@@ -129,7 +129,7 @@ end
 class CmdCall
        super CmdEntityList
 
-       autoinit(view, modelbuilder, mentity, mentity_name, limit, page, count, max)
+       autoinit(model, modelbuilder, filter, mentity, mentity_name, limit, page, count, max)
 
        # ModelBuilder used to retrieve AST nodes
        var modelbuilder: ModelBuilder
@@ -145,7 +145,7 @@ class CmdCall
                if not mentity isa MProperty then return new ErrorNotProperty(mentity)
 
                var mentities = new HashSet[MEntity]
-               for mpropdef in view.mpropdefs do
+               for mpropdef in model.collect_mpropdefs(filter) do
                        if mpropdef.mproperty == mentity then continue
                        var visitor = new MPropertyCallVisitor
                        var npropdef = modelbuilder.mpropdef2node(mpropdef)
index c5d03a3..24d1593 100644 (file)
@@ -17,6 +17,7 @@ module test_commands
 
 import commands_base
 import frontend
+import frontend::parse_examples
 
 # Nitunit test suite specific to commands
 class TestCommands
@@ -31,12 +32,15 @@ class TestCommands
        # Default is `$NIT_DIR/tests/test_prog`.
        var test_src: String = test_path / "../../../../tests/test_prog" is lazy
 
-       # ModelView used for tests
-       var test_view: ModelView is noinit
+       # Model used for tests
+       var test_model: Model is noinit
 
        # ModelBuilder used for tests
        var test_builder: ModelBuilder is noinit
 
+       # Mainmodule used for tests
+       var test_main: MModule is noinit
+
        # Initialize test variables
        #
        # Must be called before test execution.
@@ -54,13 +58,8 @@ class TestCommands
                toolcontext.run_global_phases(mmodules)
                var mainmodule = toolcontext.make_main_module(mmodules)
 
-               # Build index
-               var filters = new ModelFilter(
-                       private_visibility,
-                       accept_fictive = false,
-                       accept_test = true)
-
+               test_main = mainmodule
+               test_model = model
                test_builder = modelbuilder
-               test_view = new ModelView(model, mainmodule, filters)
        end
 end
index 07e82d8..5e921b5 100644 (file)
@@ -26,7 +26,7 @@ class TestCommandsCatalog
                var catalog = new Catalog(test_builder)
 
                # Compute the poset
-               for p in test_view.mpackages do
+               for p in test_model.mpackages do
                        var g = p.root
                        assert g != null
                        test_builder.scan_group(g)
@@ -41,7 +41,7 @@ class TestCommandsCatalog
                        end
                end
                # Build the catalog
-               for mpackage in test_view.mpackages do
+               for mpackage in test_model.mpackages do
                        catalog.package_page(mpackage)
                        catalog.git_info(mpackage)
                        catalog.mpackage_stats(mpackage)
@@ -50,36 +50,53 @@ class TestCommandsCatalog
        end
 
        fun test_cmd_catalog is test do
-               var cmd = new CmdCatalogPackages(test_view, test_catalog)
+               var cmd = new CmdCatalogPackages(test_model, test_catalog)
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).first.full_name == "test_prog"
        end
 
        fun test_cmd_catalog_search is test do
-               var cmd = new CmdCatalogSearch(test_view, test_catalog, "testprog")
+               var cmd = new CmdCatalogSearch(test_model, test_catalog, query = "testprog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).first.full_name == "test_prog"
                assert cmd.results.as(not null).first isa MPackage
        end
 
+       fun test_cmd_catalog_search_without_filter is test do
+               var cmd = new CmdCatalogSearch(test_model, test_catalog, query = "MyGame")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).first.full_name == "test_prog::MyGame"
+               assert cmd.results.as(not null).first isa MClass
+       end
+
+       fun test_cmd_catalog_search_with_filter is test do
+               var filter = new ModelFilter(accept_example = false)
+               var cmd = new CmdCatalogSearch(test_model, test_catalog, filter, query = "MGame")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).first.full_name == "test_prog::Game" # not MyGame
+               assert cmd.results.as(not null).first isa MClass
+       end
+
        fun test_cmd_catalog_stats is test do
-               var cmd = new CmdCatalogStats(test_view, test_catalog)
+               var cmd = new CmdCatalogStats(test_model, test_catalog)
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.stats != null
        end
 
        fun test_cmd_catalog_tags is test do
-               var cmd = new CmdCatalogTags(test_view, test_catalog)
+               var cmd = new CmdCatalogTags(test_model, test_catalog)
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.packages_count_by_tags.as(not null).length == 2
        end
 
        fun test_cmd_catalog_tag is test do
-               var cmd = new CmdCatalogTag(test_view, test_catalog, "test")
+               var cmd = new CmdCatalogTag(test_model, test_catalog, tag = "test")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.tag == "test"
@@ -87,14 +104,15 @@ class TestCommandsCatalog
        end
 
        fun test_cmd_catalog_person is test do
-               var cmd = new CmdCatalogPerson(test_view, test_catalog, person_name = "Alexandre Terrasa")
+               var cmd = new CmdCatalogPerson(test_model, test_catalog,
+                       person_name = "Alexandre Terrasa")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.person.as(not null).name == "Alexandre Terrasa"
        end
 
        fun test_cmd_catalog_contributing is test do
-               var cmd = new CmdCatalogContributing(test_view, test_catalog,
+               var cmd = new CmdCatalogContributing(test_model, test_catalog,
                        person_name = "Alexandre Terrasa")
                var res = cmd.init_command
                assert res isa CmdSuccess
@@ -103,7 +121,7 @@ class TestCommandsCatalog
        end
 
        fun test_cmd_catalog_maintaining is test do
-               var cmd = new CmdCatalogMaintaining(test_view, test_catalog,
+               var cmd = new CmdCatalogMaintaining(test_model, test_catalog,
                        person_name = "Alexandre Terrasa")
                var res = cmd.init_command
                assert res isa CmdSuccess
index 04f5966..d9cefa9 100644 (file)
@@ -22,28 +22,28 @@ class TestCommandsGraph
        test
 
        fun test_cmd_uml is test do
-               var cmd = new CmdUML(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdUML(test_model, test_main, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.uml != null
        end
 
        fun test_cmd_uml_bad_format is test do
-               var cmd = new CmdUML(test_view, mentity_name = "test_prog::Character", format = "foo")
+               var cmd = new CmdUML(test_model, test_main, mentity_name = "test_prog::Character", format = "foo")
                var res = cmd.init_command
                assert res isa ErrorBadGraphFormat
                assert cmd.uml == null
        end
 
        fun test_cmd_uml_not_found is test do
-               var cmd = new CmdUML(test_view, mentity_name = "strength_bonus")
+               var cmd = new CmdUML(test_model, test_main, mentity_name = "strength_bonus")
                var res = cmd.init_command
                assert res isa WarningNoUML
                assert cmd.uml == null
        end
 
        fun test_cmd_inh_graph is test do
-               var cmd = new CmdInheritanceGraph(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdInheritanceGraph(test_model, test_main, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.graph != null
diff --git a/src/doc/commands/tests/test_commands_html.sav/test_cmd_search.res b/src/doc/commands/tests/test_commands_html.sav/test_cmd_search.res
deleted file mode 100644 (file)
index a6b9ace..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<ul><li><a href="test_prog_58d_58dCareer" title="A `Career` gives a characteristic bonus or malus to the character.">Career</a> - <span class="synopsys nitdoc">A <code class="nitcode"><span class="nitcode"><span class="line"><span class="nc_t">Career</span></span></span></code> gives a characteristic bonus or malus to the character.</span></li><li><a href="test_prog_58d_58dCharacter_58d_58dcareer" title="The current `Career` of the character.">career</a> - <span class="synopsys nitdoc">The current <code class="nitcode"><span class="nitcode"><span class="line"><span class="nc_t">Career</span></span></span></code> of the character.</span></li><li><a href="test_prog_62dgame_62d" title="Gaming group">game</a> - <span class="synopsys nitdoc">Gaming group</span></li><li><a href="test_prog_58d_58dgame" title="A game abstraction for RPG.">game</a> - <span class="synopsys nitdoc">A game abstraction for RPG.</span></li><li><a href="test_prog_58d_58draces" title="Races of the game.">races</a> - <span class="synopsys nitdoc">Races of the game.</span></li><li><a href="test_prog_58d_58dcareers" title="Careers of the game.">careers</a> - <span class="synopsys nitdoc">Careers of the game.</span></li><li><a href="test_prog_58d_58dGame" title="This is the interface you have to implement to use ure gaming platform.">Game</a> - <span class="synopsys nitdoc">This is the interface you have to implement to use ure gaming platform.</span></li><li><a href="test_prog_58d_58dRace" title="Race determines basic characteristics and what the character will be able to do in life.">Race</a> - <span class="synopsys nitdoc">Race determines basic characteristics and what the character will be able to do in life.</span></li><li><a href="test_prog_58d_58dStarter">Starter</a></li><li><a href="test_prog_58d_58dCharacter_58d_58dage">age</a></li></ul>
index f2d5e18..57f5dd6 100644 (file)
@@ -38,15 +38,15 @@ class TestCommandsHttp
 
        fun test_cmd_http_entity is test do
                var req = new_request("/test_prog::Character")
-               var cmd = new CmdEntity(test_view)
+               var cmd = new CmdEntity(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.mentity.as(not null).full_name == "test_prog::Character"
        end
 
        fun test_cmd_http_entity_not_found is test do
-               var req = new_request("/Characterzzz")
-               var cmd = new CmdEntity(test_view)
+               var req = new_request("/Characterz")
+               var cmd = new CmdEntity(test_model)
                var res = cmd.http_init(req)
                assert res isa ErrorMEntityNotFound
                assert res.suggestions.first.full_name == "test_prog::Character"
@@ -54,7 +54,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_entity_conflict is test do
                var req = new_request("/+")
-               var cmd = new CmdEntity(test_view)
+               var cmd = new CmdEntity(test_model)
                var res = cmd.http_init(req)
                assert res isa ErrorMEntityConflict
                assert res.conflicts.length == 2
@@ -64,7 +64,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_comment is test do
                var req = new_request("/test_prog::Character")
-               var cmd = new CmdComment(test_view)
+               var cmd = new CmdComment(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.mdoc != null
@@ -72,7 +72,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_comment_no_mdoc is test do
                var req = new_request("/test_prog::Character?fallback=false")
-               var cmd = new CmdComment(test_view)
+               var cmd = new CmdComment(test_model)
                var res = cmd.http_init(req)
                assert res isa WarningNoMDoc
        end
@@ -81,7 +81,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_link is test do
                var req = new_request("/test_prog::Character")
-               var cmd = new CmdEntityLink(test_view)
+               var cmd = new CmdEntityLink(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.text == "Character"
@@ -90,7 +90,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_link_with_text is test do
                var req = new_request("/test_prog::Character?text=foo")
-               var cmd = new CmdEntityLink(test_view)
+               var cmd = new CmdEntityLink(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.text == "foo"
@@ -99,7 +99,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_link_with_title is test do
                var req = new_request("/test_prog::Character?title=bar")
-               var cmd = new CmdEntityLink(test_view)
+               var cmd = new CmdEntityLink(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.text == "Character"
@@ -108,7 +108,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_link_with_text_and_title is test do
                var req = new_request("/test_prog::Character?text=foo&title=bar")
-               var cmd = new CmdEntityLink(test_view)
+               var cmd = new CmdEntityLink(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.text == "foo"
@@ -119,7 +119,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_parents is test do
                var req = new_request("/test_prog::Warrior")
-               var cmd = new CmdParents(test_view)
+               var cmd = new CmdParents(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 1
@@ -127,7 +127,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_ancestors is test do
                var req = new_request("/test_prog::Warrior")
-               var cmd = new CmdAncestors(test_view)
+               var cmd = new CmdAncestors(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 2
@@ -135,7 +135,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_ancestorsi_without_parents is test do
                var req = new_request("/test_prog::Warrior?parents=false")
-               var cmd = new CmdAncestors(test_view)
+               var cmd = new CmdAncestors(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 1
@@ -143,7 +143,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_children is test do
                var req = new_request("/test_prog::Career")
-               var cmd = new CmdChildren(test_view)
+               var cmd = new CmdChildren(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 3
@@ -151,17 +151,25 @@ class TestCommandsHttp
 
        fun test_cmd_http_descendants is test do
                var req = new_request("/test_prog::Career?children=false")
-               var cmd = new CmdDescendants(test_view)
+               var cmd = new CmdDescendants(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 0
        end
 
+       fun test_cmd_http_ancestors_with_filter_match is test do
+               var req = new_request("/test_prog::Warrior?match=Object")
+               var cmd = new CmdAncestors(test_model, test_main)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
        # CmdSearch
 
        fun test_cmd_http_search is test do
                var req = new_request("/?q=Carer&l=1")
-               var cmd = new CmdSearch(test_view)
+               var cmd = new CmdSearch(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).first.full_name == "test_prog::Career"
@@ -170,7 +178,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_search_no_query is test do
                var req = new_request("/")
-               var cmd = new CmdSearch(test_view)
+               var cmd = new CmdSearch(test_model)
                var res = cmd.http_init(req)
                assert res isa ErrorNoQuery
        end
@@ -179,7 +187,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_features is test do
                var req = new_request("/test_prog::Character?l=10")
-               var cmd = new CmdFeatures(test_view)
+               var cmd = new CmdFeatures(test_model)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 10
@@ -187,16 +195,24 @@ class TestCommandsHttp
 
        fun test_cmd_http_features_no_features is test do
                var req = new_request("/test_prog$Career$strength_bonus?l=10")
-               var cmd = new CmdFeatures(test_view)
+               var cmd = new CmdFeatures(test_model)
                var res = cmd.http_init(req)
                assert res isa WarningNoFeatures
        end
 
+       fun test_cmd_http_features_with_filter_inherited is test do
+               var req = new_request("/test_prog::TestGame?inherited=TestGame")
+               var cmd = new CmdFeatures(test_model)
+               var res = cmd.http_init(req)
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 3
+       end
+
        # CmdLinearization
 
        fun test_cmd_http_lin is test do
                var req = new_request("/init?l=10")
-               var cmd = new CmdLinearization(test_view)
+               var cmd = new CmdLinearization(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 10
@@ -204,7 +220,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_lin_no_lin is test do
                var req = new_request("/test_prog?l=10")
-               var cmd = new CmdLinearization(test_view)
+               var cmd = new CmdLinearization(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa WarningNoLinearization
        end
@@ -213,7 +229,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_code is test do
                var req = new_request("/test_prog::Career")
-               var cmd = new CmdEntityCode(test_view, test_builder)
+               var cmd = new CmdEntityCode(test_model, test_builder)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.node isa AStdClassdef
@@ -222,7 +238,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_code_format is test do
                var req = new_request("/test_prog::Career?format=html")
-               var cmd = new CmdEntityCode(test_view, test_builder)
+               var cmd = new CmdEntityCode(test_model, test_builder)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.node isa AStdClassdef
@@ -231,7 +247,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_code_no_code is test do
                var req = new_request("/test_prog")
-               var cmd = new CmdEntityCode(test_view, test_builder)
+               var cmd = new CmdEntityCode(test_model, test_builder)
                var res = cmd.http_init(req)
                assert res isa WarningNoCode
        end
@@ -240,7 +256,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_results is test do
                var req = new_request("/?kind=modules&l=2")
-               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var cmd = new CmdModelEntities(test_model, kind = "modules")
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 2
@@ -248,7 +264,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_results_random is test do
                var req = new_request("/?kind=packages&l=1")
-               var cmd = new CmdRandomEntities(test_view, kind = "packages")
+               var cmd = new CmdRandomEntities(test_model, kind = "packages")
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 1
@@ -258,7 +274,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_uml is test do
                var req = new_request("/test_prog::Character?format=svg")
-               var cmd = new CmdUML(test_view)
+               var cmd = new CmdUML(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.uml != null
@@ -267,7 +283,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_uml_not_found is test do
                var req = new_request("/strength_bonus")
-               var cmd = new CmdUML(test_view)
+               var cmd = new CmdUML(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa WarningNoUML
                assert cmd.format == "dot"
@@ -276,7 +292,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_inh_graph is test do
                var req = new_request("/test_prog::Character?pdepth=1&cdepth=1")
-               var cmd = new CmdInheritanceGraph(test_view)
+               var cmd = new CmdInheritanceGraph(test_model, test_main)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.graph != null
@@ -288,7 +304,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_catalog_search is test do
                var req = new_request("/?q=testprog&l=1")
-               var cmd = new CmdCatalogSearch(test_view, test_catalog)
+               var cmd = new CmdCatalogSearch(test_model, test_catalog)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.results.as(not null).first.full_name == "test_prog"
@@ -298,7 +314,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_catalog_tag is test do
                var req = new_request("/test", "/:tid")
-               var cmd = new CmdCatalogTag(test_view, test_catalog)
+               var cmd = new CmdCatalogTag(test_model, test_catalog)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.tag == "test"
@@ -307,7 +323,7 @@ class TestCommandsHttp
 
        fun test_cmd_http_catalog_person is test do
                var req = new_request("/Alexandre%20Terrasa", "/:pid")
-               var cmd = new CmdCatalogPerson(test_view, test_catalog)
+               var cmd = new CmdCatalogPerson(test_model, test_catalog)
                var res = cmd.http_init(req)
                assert res isa CmdSuccess
                assert cmd.person.as(not null).name == "Alexandre Terrasa"
index e2c02b7..15b4fa1 100644 (file)
@@ -24,21 +24,21 @@ class TestCommandsIni
        # CmdIni
 
        fun test_cmd_ini_desc is test do
-               var cmd = new CmdIniDescription(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniDescription(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.desc == "Dummy program used for testing Nit tools"
        end
 
        fun test_cmd_ini_git is test do
-               var cmd = new CmdIniGitUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniGitUrl(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.url == "https://github.com/nitlang/nit.git"
        end
 
        fun test_cmd_ini_clone is test do
-               var cmd = new CmdIniCloneCommand(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniCloneCommand(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.url == "https://github.com/nitlang/nit.git"
@@ -46,21 +46,21 @@ class TestCommandsIni
        end
 
        fun test_cmd_ini_issues is test do
-               var cmd = new CmdIniIssuesUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniIssuesUrl(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.url == "https://github.com/nitlang/nit/issues"
        end
 
        fun test_cmd_ini_maintainer is test do
-               var cmd = new CmdIniMaintainer(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniMaintainer(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.maintainer == "John Doe <jdoe@example.com> (http://www.example.com/~jdoe), Spider-Man"
        end
 
        fun test_cmd_ini_contributors is test do
-               var cmd = new CmdIniContributors(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniContributors(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.contributors == [
@@ -70,14 +70,14 @@ class TestCommandsIni
        end
 
        fun test_cmd_ini_license is test do
-               var cmd = new CmdIniLicense(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniLicense(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.license == "Apache-2.0"
        end
 
        fun test_cmd_ini_license_file is test do
-               var cmd = new CmdLicenseFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFile(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
@@ -87,7 +87,7 @@ class TestCommandsIni
        end
 
        fun test_cmd_ini_license_file_content is test do
-               var cmd = new CmdLicenseFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFileContent(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
@@ -97,7 +97,7 @@ class TestCommandsIni
        end
 
        fun test_cmd_ini_contrib_file is test do
-               var cmd = new CmdContribFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFile(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
@@ -107,7 +107,7 @@ class TestCommandsIni
        end
 
        fun test_cmd_ini_contrib_file_content is test do
-               var cmd = new CmdContribFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFileContent(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
diff --git a/src/doc/commands/tests/test_commands_json.sav/test_cmd_search.res b/src/doc/commands/tests/test_commands_json.sav/test_cmd_search.res
deleted file mode 100644 (file)
index d58aef9..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-{
-       "results": [{
-               "name": "Career",
-               "synopsis": "A `Career` gives a characteristic bonus or malus to the character.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Career",
-                       "synopsis": "A `Career` gives a characteristic bonus or malus to the character."
-               }],
-               "class_name": "MClass",
-               "full_name": "test_prog::Career",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">A <code class=\"nitcode\"><span class=\"nitcode\"><span class=\"line\"><span class=\"nc_t\">Career</span></span></span></code> gives a characteristic bonus or malus to the character.</span>",
-               "modifiers": ["abstract class"]
-       }, {
-               "name": "career",
-               "synopsis": "The current `Career` of the character.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Character",
-                       "synopsis": "Characters can be played by both the human or the machine."
-               }, "::", {
-                       "name": "career",
-                       "synopsis": "The current `Career` of the character."
-               }],
-               "class_name": "MMethod",
-               "full_name": "test_prog::Character::career",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">The current <code class=\"nitcode\"><span class=\"nitcode\"><span class=\"line\"><span class=\"nc_t\">Career</span></span></span></code> of the character.</span>",
-               "modifiers": ["fun"],
-               "msignature": {
-                       "arity": 0,
-                       "mparameters": [],
-                       "return_mtype": {
-                               "name": "nullable Career",
-                               "synopsis": "A `Career` gives a characteristic bonus or malus to the character.",
-                               "html_synopsis": "<span class=\"synopsys nitdoc\">A <code class=\"nitcode\"><span class=\"nitcode\"><span class=\"line\"><span class=\"nc_t\">Career</span></span></span></code> gives a characteristic bonus or malus to the character.</span>"
-                       }
-               }
-       }, {
-               "name": "game",
-               "synopsis": "Gaming group",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, ">", {
-                       "name": "game",
-                       "synopsis": "Gaming group"
-               }, ">"],
-               "class_name": "MGroup",
-               "full_name": "test_prog>game>",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">Gaming group</span>",
-               "modifiers": ["group"]
-       }, {
-               "name": "game",
-               "synopsis": "A game abstraction for RPG.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "game",
-                       "synopsis": "A game abstraction for RPG."
-               }],
-               "class_name": "MModule",
-               "full_name": "test_prog::game",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">A game abstraction for RPG.</span>",
-               "modifiers": ["module"]
-       }, {
-               "name": "races",
-               "synopsis": "Races of the game.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "races",
-                       "synopsis": "Races of the game."
-               }],
-               "class_name": "MModule",
-               "full_name": "test_prog::races",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">Races of the game.</span>",
-               "modifiers": ["module"]
-       }, {
-               "name": "careers",
-               "synopsis": "Careers of the game.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "careers",
-                       "synopsis": "Careers of the game."
-               }],
-               "class_name": "MModule",
-               "full_name": "test_prog::careers",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">Careers of the game.</span>",
-               "modifiers": ["module"]
-       }, {
-               "name": "Game",
-               "synopsis": "This is the interface you have to implement to use ure gaming platform.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Game",
-                       "synopsis": "This is the interface you have to implement to use ure gaming platform."
-               }],
-               "class_name": "MClass",
-               "full_name": "test_prog::Game",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">This is the interface you have to implement to use ure gaming platform.</span>",
-               "modifiers": ["interface"]
-       }, {
-               "name": "Race",
-               "synopsis": "Race determines basic characteristics and what the character will be able to do in life.",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Race",
-                       "synopsis": "Race determines basic characteristics and what the character will be able to do in life."
-               }],
-               "class_name": "MClass",
-               "full_name": "test_prog::Race",
-               "visibility": "public",
-               "html_synopsis": "<span class=\"synopsys nitdoc\">Race determines basic characteristics and what the character will be able to do in life.</span>",
-               "modifiers": ["abstract class"]
-       }, {
-               "name": "Starter",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Starter"
-               }],
-               "class_name": "MClass",
-               "full_name": "test_prog::Starter",
-               "visibility": "public",
-               "modifiers": ["class"]
-       }, {
-               "name": "age",
-               "namespace": [{
-                       "name": "test_prog",
-                       "synopsis": "Test program for model tools."
-               }, "::", {
-                       "name": "Character",
-                       "synopsis": "Characters can be played by both the human or the machine."
-               }, "::", {
-                       "name": "age"
-               }],
-               "class_name": "MMethod",
-               "full_name": "test_prog::Character::age",
-               "visibility": "public",
-               "modifiers": ["fun"],
-               "msignature": {
-                       "arity": 0,
-                       "mparameters": [],
-                       "return_mtype": {
-                               "name": "Int",
-                               "synopsis": "Some services about Integers.",
-                               "html_synopsis": "<span class=\"synopsys nitdoc\">Some services about Integers.</span>"
-                       }
-               }
-       }],
-       "page": 1,
-       "count": 121,
-       "limit": 10,
-       "max": 12
-}
index 5715cc2..241b2f6 100644 (file)
@@ -22,7 +22,7 @@ class TestCommandsMain
        test
 
        fun test_cmd_mains is test do
-               var cmd = new CmdMains(test_view, mentity_name = "test_prog")
+               var cmd = new CmdMains(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                var results = cmd.results
@@ -32,7 +32,7 @@ class TestCommandsMain
        end
 
        fun test_cmd_main_compile is test do
-               var cmd = new CmdMainCompile(test_view, mentity_name = "test_prog::test_prog")
+               var cmd = new CmdMainCompile(test_model, mentity_name = "test_prog::test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
@@ -43,7 +43,7 @@ class TestCommandsMain
        end
 
        fun test_cmd_testing is test do
-               var cmd = new CmdTesting(test_view, mentity_name = "test_prog")
+               var cmd = new CmdTesting(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
@@ -54,14 +54,14 @@ class TestCommandsMain
        end
 
        fun test_cmd_man_synopsis is test do
-               var cmd = new CmdManSynopsis(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManSynopsis(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.synopsis == "test_prog [*options*] ARGS..."
        end
 
        fun test_cmd_man_options is test do
-               var cmd = new CmdManOptions(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManOptions(test_model, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa CmdSuccess
 
diff --git a/src/doc/commands/tests/test_commands_md.sav/test_cmd_search.res b/src/doc/commands/tests/test_commands_md.sav/test_cmd_search.res
deleted file mode 100644 (file)
index 577166b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-* `Career` - A `Career` gives a characteristic bonus or malus to the character.
-* `career` - The current `Career` of the character.
-* `game` - Gaming group
-* `game` - A game abstraction for RPG.
-* `races` - Races of the game.
-* `careers` - Careers of the game.
-* `Game` - This is the interface you have to implement to use ure gaming platform.
-* `Race` - Race determines basic characteristics and what the character will be able to do in life.
-* `Starter`
-* `age`
index 88d5e5e..4847987 100644 (file)
@@ -24,28 +24,28 @@ class TestCommandsModel
        # CmdEntity
 
        fun test_cmd_entity is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntity(test_model, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.mentity.as(not null).full_name == "test_prog::Character"
        end
 
        fun test_cmd_entity_not_found is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "test_prog::Characterzz")
+               var cmd = new CmdEntity(test_model, mentity_name = "test_prog::Characterz")
                var res = cmd.init_command
                assert res isa ErrorMEntityNotFound
                assert res.suggestions.first.full_name == "test_prog::Character"
        end
 
        fun test_cmd_entity_conflict is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "+")
+               var cmd = new CmdEntity(test_model, mentity_name = "+")
                var res = cmd.init_command
                assert res isa ErrorMEntityConflict
                assert res.conflicts.length == 2
        end
 
        fun test_cmd_entity_no_name is test do
-               var cmd = new CmdEntity(test_view)
+               var cmd = new CmdEntity(test_model)
                var res = cmd.init_command
                assert res isa ErrorMEntityNoName
        end
@@ -53,14 +53,14 @@ class TestCommandsModel
        # CmdComment
 
        fun test_cmd_comment is test do
-               var cmd = new CmdComment(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdComment(test_model, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.mdoc != null
        end
 
        fun test_cmd_comment_no_mdoc is test do
-               var cmd = new CmdComment(test_view, mentity_name = "test_prog::Character", fallback = false)
+               var cmd = new CmdComment(test_model, mentity_name = "test_prog::Character", fallback = false)
                var res = cmd.init_command
                assert res isa WarningNoMDoc
        end
@@ -68,7 +68,7 @@ class TestCommandsModel
        # CmdLink
 
        fun test_cmd_link is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.text == "Character"
@@ -76,7 +76,7 @@ class TestCommandsModel
        end
 
        fun test_cmd_link_with_text is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character", text = "foo")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character", text = "foo")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.text == "foo"
@@ -84,7 +84,7 @@ class TestCommandsModel
        end
 
        fun test_cmd_link_with_title is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character", title = "bar")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character", title = "bar")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.text == "Character"
@@ -92,7 +92,7 @@ class TestCommandsModel
        end
 
        fun test_cmd_link_with_text_and_title is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character",
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character",
                        text = "foo", title = "bar")
                var res = cmd.init_command
                assert res isa CmdSuccess
@@ -103,35 +103,58 @@ class TestCommandsModel
        # CmdInheritance
 
        fun test_cmd_parents is test do
-               var cmd = new CmdParents(test_view, mentity_name = "test_prog::Warrior")
+               var cmd = new CmdParents(test_model, test_main, mentity_name = "test_prog::Warrior")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 1
        end
 
        fun test_cmd_ancestors is test do
-               var cmd = new CmdAncestors(test_view, mentity_name = "test_prog::Warrior")
+               var cmd = new CmdAncestors(test_model, test_main, mentity_name = "test_prog::Warrior")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 2
        end
 
-       fun test_cmd_ancestorsi_without_parents is test do
-               var cmd = new CmdAncestors(test_view, mentity_name = "test_prog::Warrior", parents = false)
+       fun test_cmd_ancestors_without_parents is test do
+               var cmd = new CmdAncestors(test_model, test_main, mentity_name = "test_prog::Warrior", parents = false)
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 1
        end
 
        fun test_cmd_children is test do
-               var cmd = new CmdChildren(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdChildren(test_model, test_main, mentity_name = "test_prog::Career")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 3
        end
 
+       fun test_cmd_children_without_filter is test do
+               var cmd = new CmdDescendants(test_model, test_main, mentity_name = "test_prog::Game")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 2
+       end
+
+       fun test_cmd_children_with_filter_example is test do
+               var filter = new ModelFilter(accept_example = false)
+               var cmd = new CmdDescendants(test_model, test_main, filter, mentity_name = "test_prog::Game")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
+       fun test_cmd_children_with_filter_match is test do
+               var filter = new ModelFilter(accept_full_name = "MyGame")
+               var cmd = new CmdDescendants(test_model, test_main, filter, mentity_name = "test_prog::Game")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 1
+       end
+
        fun test_cmd_descendants is test do
-               var cmd = new CmdDescendants(test_view, mentity_name = "test_prog::Career", children = false)
+               var cmd = new CmdDescendants(test_model, test_main, mentity_name = "test_prog::Career", children = false)
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 0
@@ -140,14 +163,14 @@ class TestCommandsModel
        # CmdSearch
 
        fun test_cmd_search is test do
-               var cmd = new CmdSearch(test_view, query = "Carer")
+               var cmd = new CmdSearch(test_model, query = "Carer")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).first.full_name == "test_prog::Career"
        end
 
        fun test_cmd_search_no_query is test do
-               var cmd = new CmdSearch(test_view)
+               var cmd = new CmdSearch(test_model)
                var res = cmd.init_command
                assert res isa ErrorNoQuery
        end
@@ -155,14 +178,47 @@ class TestCommandsModel
        # CmdFeatures
 
        fun test_cmd_features is test do
-               var cmd = new CmdFeatures(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdFeatures(test_model, mentity_name = "test_prog::Career")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 10
        end
 
+       fun test_cmd_features_with_filter_attribute is test do
+               var filter = new ModelFilter(accept_attribute = false)
+               var cmd = new CmdFeatures(test_model, filter, mentity_name = "test_prog::Career")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 7
+       end
+
+       fun test_cmd_features_with_filter_public is test do
+               var filter = new ModelFilter(min_visibility = public_visibility)
+               var cmd = new CmdFeatures(test_model, filter, mentity_name = "test_prog::Career")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 4
+       end
+
+       fun test_cmd_features_with_filter_match is test do
+               var filter = new ModelFilter(accept_full_name = "endurance")
+               var cmd = new CmdFeatures(test_model, filter, mentity_name = "test_prog::Career")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 3
+       end
+
+       fun test_cmd_features_with_filter_inh is test do
+               var context = test_model.mentity_by_full_name("test_prog::TestGame").as(not null)
+               var filter = new ModelFilter(accept_inherited = context)
+               var cmd = new CmdFeatures(test_model, filter, mentity_name = "test_prog::TestGame")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               assert cmd.results.as(not null).length == 3
+       end
+
        fun test_cmd_features_no_features is test do
-               var cmd = new CmdFeatures(test_view, mentity_name = "test_prog$Career$strength_bonus")
+               var cmd = new CmdFeatures(test_model, mentity_name = "test_prog$Career$strength_bonus")
                var res = cmd.init_command
                assert res isa WarningNoFeatures
        end
@@ -170,15 +226,14 @@ class TestCommandsModel
        # CmdLinearization
 
        fun test_cmd_lin is test do
-               var cmd = new CmdLinearization(test_view, mentity_name = "init")
+               var cmd = new CmdLinearization(test_model, test_main, mentity_name = "init")
                var res = cmd.init_command
                assert res isa CmdSuccess
-               print cmd.results.as(not null)
                assert cmd.results.as(not null).length == 10
        end
 
        fun test_cmd_lin_no_lin is test do
-               var cmd = new CmdLinearization(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLinearization(test_model, test_main, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa WarningNoLinearization
        end
@@ -186,14 +241,14 @@ class TestCommandsModel
        # CmdCode
 
        fun test_cmd_code is test do
-               var cmd = new CmdEntityCode(test_view, test_builder, mentity_name = "test_prog::Career")
+               var cmd = new CmdEntityCode(test_model, test_builder, mentity_name = "test_prog::Career")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.node isa AStdClassdef
        end
 
        fun test_cmd_code_no_code is test do
-               var cmd = new CmdEntityCode(test_view, test_builder, mentity_name = "test_prog")
+               var cmd = new CmdEntityCode(test_model, test_builder, mentity_name = "test_prog")
                var res = cmd.init_command
                assert res isa WarningNoCode
        end
@@ -201,14 +256,23 @@ class TestCommandsModel
        # CmdModel
 
        fun test_cmd_results is test do
-               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var cmd = new CmdModelEntities(test_model, kind = "modules")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 11
        end
 
+       fun test_cmd_results_with_filter is test do
+               var filter = new ModelFilter(accept_test = false, accept_example = false)
+               var cmd = new CmdModelEntities(test_model, filter, kind = "modules")
+               var res = cmd.init_command
+               assert res isa CmdSuccess
+               print cmd.results.as(not null)
+               assert cmd.results.as(not null).length == 9
+       end
+
        fun test_cmd_results_random is test do
-               var cmd = new CmdRandomEntities(test_view, kind = "packages")
+               var cmd = new CmdRandomEntities(test_model, kind = "packages")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results.as(not null).length == 2
index e9f299c..41cc36b 100644 (file)
@@ -25,7 +25,7 @@ class TestCommandsParser
        # CmdEntity
 
        fun test_cmd_parser_comment is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("doc: test_prog::Character")
                assert cmd isa CmdComment
                assert parser.error == null
@@ -33,7 +33,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_link is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("link: test_prog::Character")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -42,7 +42,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_link_with_text is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("link: test_prog::Character | text: foo")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -51,7 +51,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_link_with_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("link: test_prog::Character | title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -60,7 +60,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_link_with_text_and_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("link: test_prog::Character | text: foo, title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -69,7 +69,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("test_prog::Character")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -78,7 +78,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_text is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("test_prog::Character | text: foo")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -87,7 +87,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("test_prog::Character | title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -96,7 +96,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_text_and_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("test_prog::Character | text: foo, title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -105,7 +105,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_name is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("Character")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -114,7 +114,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_name_and_text is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("Character | text: foo")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -123,7 +123,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_name_and_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("Character | title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -132,7 +132,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_short_link_with_name_and_text_and_title is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                var cmd = parser.parse("Character | text: foo, title: bar")
                assert cmd isa CmdEntityLink
                assert parser.error == null
@@ -143,7 +143,7 @@ class TestCommandsParser
        # CmdInheritance
 
        fun test_cmd_parser_parents is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("parents: test_prog::Warrior")
                assert cmd isa CmdParents
                assert parser.error == null
@@ -151,7 +151,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ancestors is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ancestors: test_prog::Warrior")
                assert cmd isa CmdAncestors
                assert parser.error == null
@@ -159,15 +159,15 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ancestors_without_parents is test do
-               var parser = new CommandParser(test_view, test_builder)
-               var cmd = parser.parse("ancestors: test_prog::Warrior | parents: false")
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
+               var cmd = parser.parse("ancestors: test_prog::Warrior | no-parents")
                assert cmd isa CmdAncestors
                assert parser.error == null
                assert cmd.results.as(not null).length == 1
        end
 
        fun test_cmd_parser_children is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("children: test_prog::Career")
                assert cmd isa CmdChildren
                assert parser.error == null
@@ -175,7 +175,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_descendants is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("descendants: Object")
                assert cmd isa CmdDescendants
                assert parser.error == null
@@ -183,17 +183,25 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_descendants_without_children is test do
-               var parser = new CommandParser(test_view, test_builder)
-               var cmd = parser.parse("descendants: Object | children: false")
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
+               var cmd = parser.parse("descendants: Object | no-children: true")
                assert cmd isa CmdDescendants
                assert parser.error == null
                assert cmd.results.as(not null).length == 9
        end
 
+       fun test_cmd_parser_ancestors_with_filter_match is test do
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
+               var cmd = parser.parse("ancestors: test_prog::Warrior | match: Object")
+               assert cmd isa CmdAncestors
+               assert parser.error == null
+               assert cmd.results.as(not null).length == 1
+       end
+
        # CmdSearch
 
        fun test_cmd_parser_search is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("search: Caracter")
                assert cmd isa CmdSearch
                assert parser.error == null
@@ -201,8 +209,8 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_search_limit is test do
-               var parser = new CommandParser(test_view, test_builder)
-               var cmd = parser.parse("search: Caracter | limit: 2")
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
+               var cmd = parser.parse("search: strength | limit: 2")
                assert cmd isa CmdSearch
                assert parser.error == null
                assert cmd.results.as(not null).length == 2
@@ -211,7 +219,7 @@ class TestCommandsParser
        # CmdFeatures
 
        fun test_cmd_parser_features is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("defs: test_prog::Character")
                assert cmd isa CmdFeatures
                assert parser.error == null
@@ -219,17 +227,25 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_features_limit is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("defs: test_prog::Character | limit: 2")
                assert cmd isa CmdFeatures
                assert parser.error == null
                assert cmd.results.as(not null).length == 2
        end
 
+       fun test_cmd_parser_with_filter_inherited is test do
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
+               var cmd = parser.parse("defs: test_prog::TestGame | inherited: TestGame")
+               assert cmd isa CmdFeatures
+               assert parser.error == null
+               assert cmd.results.as(not null).length == 3
+       end
+
        # CmdLinearization
 
        fun test_cmd_parser_lin is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("lin: test_prog::Character")
                assert cmd isa CmdLinearization
                assert parser.error == null
@@ -237,7 +253,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_lin_limit is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("lin: test_prog::Character | limit: 2")
                assert cmd isa CmdLinearization
                assert parser.error == null
@@ -247,7 +263,7 @@ class TestCommandsParser
        # CmdCode
 
        fun test_cmd_parser_code is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("code: test_prog::Character")
                assert cmd isa CmdEntityCode
                assert parser.error == null
@@ -257,7 +273,7 @@ class TestCommandsParser
        # CmdModel
 
        fun test_cmd_parser_mentities is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("list: modules")
                assert cmd isa CmdModelEntities
                assert parser.error == null
@@ -265,7 +281,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_results_mentities is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("random: modules")
                assert cmd isa CmdRandomEntities
                assert parser.error == null
@@ -275,7 +291,7 @@ class TestCommandsParser
        # CmdGraph
 
        fun test_cmd_parser_uml is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("uml: test_prog::Career")
                assert cmd isa CmdUML
                assert parser.error == null
@@ -283,7 +299,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_inh_graph is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("graph: test_prog::Career")
                assert cmd isa CmdInheritanceGraph
                assert parser.error == null
@@ -291,7 +307,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_inh_graph_opts is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("graph: test_prog::Career | cdepth: 2, pdepth: 5")
                assert cmd isa CmdInheritanceGraph
                assert parser.error == null
@@ -303,7 +319,7 @@ class TestCommandsParser
        # CmdUsage
 
        fun test_cmd_parser_new is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("new: test_prog::Career")
                assert cmd isa CmdNew
                assert parser.error == null
@@ -311,7 +327,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_call is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("call: strength_bonus")
                assert cmd isa CmdCall
                assert parser.error == null
@@ -319,7 +335,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_return is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("return: test_prog::Career")
                assert cmd isa CmdReturn
                assert parser.error == null
@@ -327,7 +343,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_param is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("param: test_prog::Career")
                assert cmd isa CmdParam
                assert parser.error == null
@@ -337,7 +353,7 @@ class TestCommandsParser
        # CmdCatalog
 
        fun test_parser_catalog_search is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("search: Caracter")
                assert cmd isa CmdSearch
                assert parser.error == null
@@ -345,7 +361,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_packages is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("catalog:")
                assert cmd isa CmdCatalogPackages
                assert parser.error == null
@@ -353,7 +369,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_stats is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("stats:")
                assert cmd isa CmdCatalogStats
                assert parser.error == null
@@ -361,7 +377,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_tags is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("tags:")
                assert cmd isa CmdCatalogTags
                assert parser.error == null
@@ -369,7 +385,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_tag is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("tag: test")
                assert cmd isa CmdCatalogTag
                assert parser.error == null
@@ -378,7 +394,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_person is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("person: Alexandre Terrasa")
                assert cmd isa CmdCatalogPerson
                assert parser.error == null
@@ -386,7 +402,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_contributing is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("contrib: Alexandre Terrasa")
                assert cmd isa CmdCatalogContributing
                assert parser.error == null
@@ -395,7 +411,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_catalog_maintaining is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("maintain: Alexandre Terrasa")
                assert cmd isa CmdCatalogMaintaining
                assert parser.error == null
@@ -406,7 +422,7 @@ class TestCommandsParser
        # CmdInit
 
        fun test_cmd_parser_ini_desc is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-desc: test_prog")
                assert cmd isa CmdIniDescription
                assert parser.error == null
@@ -414,7 +430,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_git is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-git: test_prog")
                assert cmd isa CmdIniGitUrl
                assert parser.error == null
@@ -422,7 +438,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_clone is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("git-clone: test_prog")
                assert cmd isa CmdIniCloneCommand
                assert parser.error == null
@@ -431,7 +447,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_issues is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-issues: test_prog")
                assert cmd isa CmdIniIssuesUrl
                assert parser.error == null
@@ -439,7 +455,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_maintainer is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-maintainer: test_prog")
                assert cmd isa CmdIniMaintainer
                assert parser.error == null
@@ -447,7 +463,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_contributors is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-contributors: test_prog")
                assert cmd isa CmdIniContributors
                assert parser.error == null
@@ -458,7 +474,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_license is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("ini-license: test_prog")
                assert cmd isa CmdIniLicense
                assert parser.error == null
@@ -466,7 +482,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_license_file is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("license-file: test_prog")
                assert cmd isa CmdLicenseFile
                assert parser.error == null
@@ -476,7 +492,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_license_content is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("license-content: test_prog")
                assert cmd isa CmdLicenseFileContent
                assert parser.error == null
@@ -486,7 +502,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_contrib_file is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("contrib-file: test_prog")
                assert cmd isa CmdContribFile
                assert parser.error == null
@@ -496,7 +512,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_ini_contrib_content is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("contrib-content: test_prog")
                assert cmd isa CmdContribFileContent
                assert parser.error == null
@@ -508,7 +524,7 @@ class TestCommandsParser
        # CmdMain
 
        fun test_cmd_parser_mains is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("mains: test_prog")
                assert cmd isa CmdMains
                assert parser.error == null
@@ -520,7 +536,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_main_compile is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("main-compile: test_prog::test_prog")
                assert cmd isa CmdMainCompile
                assert parser.error == null
@@ -532,7 +548,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_parser_testing is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("testing: test_prog")
                assert cmd isa CmdTesting
                assert parser.error == null
@@ -544,7 +560,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_man_synopsis is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("main-run: test_prog")
                assert cmd isa CmdManSynopsis
                assert parser.error == null
@@ -553,7 +569,7 @@ class TestCommandsParser
        end
 
        fun test_cmd_man_opions is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                var cmd = parser.parse("main-opts: test_prog")
                assert cmd isa CmdManOptions
                assert parser.error == null
index b07c336..02a4028 100644 (file)
@@ -22,40 +22,40 @@ class TestCommandsUsage
        test
 
        fun test_cmd_new is test do
-               var cmd = new CmdNew(test_view, test_builder, mentity_name = "test_prog::Character")
+               var cmd = new CmdNew(test_model, test_builder, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results != null
        end
 
        fun test_cmd_new_not_class is test do
-               var cmd = new CmdNew(test_view, test_builder, mentity_name = "strength_bonus")
+               var cmd = new CmdNew(test_model, test_builder, mentity_name = "strength_bonus")
                var res = cmd.init_command
                assert res isa ErrorNotClass
        end
 
        fun test_cmd_call is test do
-               var cmd = new CmdCall(test_view, test_builder, mentity_name = "strength_bonus")
+               var cmd = new CmdCall(test_model, test_builder, mentity_name = "strength_bonus")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results != null
        end
 
        fun test_cmd_call_not_prop is test do
-               var cmd = new CmdCall(test_view, test_builder, mentity_name = "test_prog::Character")
+               var cmd = new CmdCall(test_model, test_builder, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa ErrorNotProperty
        end
 
        fun test_cmd_return is test do
-               var cmd = new CmdReturn(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdReturn(test_model, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results != null
        end
 
        fun test_cmd_param is test do
-               var cmd = new CmdParam(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdParam(test_model, mentity_name = "test_prog::Character")
                var res = cmd.init_command
                assert res isa CmdSuccess
                assert cmd.results != null
diff --git a/src/doc/doc_base.nit b/src/doc/doc_base.nit
deleted file mode 100644 (file)
index ce36170..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-# 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.
-
-# Base entities shared by all the nitdoc code.
-module doc_base
-
-import toolcontext
-import model_ext
-import model::model_views
-
-# The model of a Nitdoc documentation.
-#
-# `DocModel` contains the list of the `DocPage` to be generated.
-#
-# The model is populated through `DocPhase` to be constructed.
-# It is a placeholder to share data between each phase.
-class DocModel
-       super ModelView
-
-       autoinit model, mainmodule, filter
-
-       # `DocPage` composing the documentation associated to their ids.
-       #
-       # This is where `DocPhase` store and access pages to produce documentation.
-       #
-       # See `add_page`.
-       var pages: Map[String, DocPage] = new HashMap[String, DocPage]
-
-       # Add a `page` to this documentation.
-       fun add_page(page: DocPage) do
-               if pages.has_key(page.id) then
-                       print "Warning: multiple page with the same id `{page.id}`"
-               end
-               pages[page.id] = page
-       end
-end
-
-# A documentation page abstraction.
-#
-# The page contains a link to the `root` of the `DocComposite` that compose the
-# the page.
-class DocPage
-
-       # Page uniq id.
-       #
-       # The `id` is used as name for the generated file corresponding to the page
-       # (if any).
-       # Because multiple pages can be generated in the same directory it should be
-       # uniq.
-       #
-       # The `id` can also be used to establish links between pages (HTML links,
-       # HTML anchors, vim links, etc.).
-       var id: String is writable
-
-       # Title of this page.
-       var title: String is writable
-
-       # Root element of the page.
-       #
-       # `DocPhase` access the structure of the page from the `DocRoot`.
-       var root = new DocRoot
-
-       redef fun to_s do return title
-
-       # Pretty prints the content of this page.
-       fun pretty_print: Writable do
-               var res = new Template
-               res.addn "{class_name} {title}"
-               for child in root.children do
-                       child.pretty_print_in(res)
-               end
-               return res
-       end
-end
-
-# `DocPage` elements that can be nested in another.
-#
-# `DocComposite` is an abstraction for everything that go in a `DocPage` like
-# sections, articles, images, lists, graphs...
-#
-# It provides base services for nesting mechanisms following the
-# *Composite pattern*.
-# The composed structure is a tree from a `DocRoot` that can be manipulated
-# recursively.
-abstract class DocComposite
-
-       # Parent element.
-       var parent: nullable DocComposite = null is writable
-
-       # Element uniq id.
-       #
-       # The `id` is used as name for the generated element (if any).
-       # Because multiple elements can be generated in the same container
-       # it should be uniq.
-       #
-       # The `id` can also be used to establish links between elements
-       # (HTML links, HTML anchors, vim links, etc.).
-       var id: String is writable
-
-       # Item title if any.
-       var title: nullable String is writable
-
-       # Does `self` have a `parent`?
-       fun is_root: Bool do return parent == null
-
-       # Children elements contained in `self`.
-       #
-       # Children are ordered, this order can be changed by the `DocPhase`.
-       var children = new Array[DocComposite]
-
-       # Is `self` not displayed in the page.
-       #
-       # By default, empty elements are hidden.
-       fun is_hidden: Bool do return children.is_empty
-
-       # Title used in table of content if any.
-       var toc_title: nullable String is writable, lazy do return title
-
-       # Is `self` hidden in the table of content?
-       var is_toc_hidden: Bool is writable, lazy do
-               return toc_title == null or is_hidden
-       end
-
-       # Add a `child` to `self`.
-       #
-       # Shortcut for `children.add`.
-       fun add_child(child: DocComposite) do
-               child.parent = self
-               children.add child
-       end
-
-       # Depth of `self` in the composite tree.
-       fun depth: Int do
-               var parent = self.parent
-               if parent == null then return 0
-               return parent.depth + 1
-       end
-
-       # Pretty prints this composite recursively.
-       fun pretty_print: Writable do
-               var res = new Template
-               pretty_print_in(res)
-               return res
-       end
-
-       # Appends the Pretty print of this composite in `res`.
-       private fun pretty_print_in(res: Template) do
-               res.add "\t" * depth
-               res.add "#" * depth
-               res.addn " {id}"
-               for child in children do child.pretty_print_in(res)
-       end
-end
-
-# The `DocComposite` element that contains all the other.
-#
-# The root uses a specific subclass to provide different a different behavior
-# than other `DocComposite` elements.
-class DocRoot
-       noautoinit
-       super DocComposite
-
-       redef var id = "<root>"
-       redef var title = "<root>"
-
-       # No op for `RootSection`.
-       redef fun parent=(p) do end
-end
-
-# Base page elements.
-
-# `DocSection` are used to break the documentation page into meaningfull parts.
-#
-# The content of the documentation summary is based on the section structure
-# contained in the DocComposite tree.
-class DocSection
-       super DocComposite
-end
-
-# `DocArticle` are pieces of documentation.
-#
-# They maintains the content (text, list, image...) of a documentation page.
-class DocArticle
-       super DocComposite
-end
-
-# A DocPhase is a step in the production of a Nitdoc documentation.
-#
-# Phases work from a `DocModel`.
-# Specific phases are used to populate, organize, enhance and render the content
-# of the documentation pages.
-#
-# See `doc_phases` for available DocPhase.
-class DocPhase
-
-       # Link to the ToolContext to access Nitdoc tool options.
-       var ctx: ToolContext
-
-       # `DocModel` used by this phase to work.
-       var doc: DocModel
-
-       # Starting point of a `DocPhase`.
-       #
-       # This is where the behavior of the phase is implemented.
-       # Phases can populate, edit or render the `doc` from here.
-       fun apply is abstract
-end
-
-redef class ToolContext
-
-       # Directory where the Nitdoc is rendered.
-       var opt_dir = new OptionString("Output directory", "-d", "--dir")
-
-       # Shortcut for `opt_dir.value` with default "doc".
-       var output_dir: String is lazy do return opt_dir.value or else "doc"
-
-       redef init do
-               super
-               option_context.add_option(opt_dir)
-       end
-end
-
-# Catalog properties by kind.
-class PropertiesByKind
-       # The virtual types.
-       var virtual_types = new PropertyGroup[MVirtualTypeProp]("Virtual types")
-
-       # The constructors.
-       var constructors = new PropertyGroup[MMethod]("Contructors")
-
-       # The attributes.
-       var attributes = new PropertyGroup[MAttribute]("Attributes")
-
-       # The methods.
-       var methods = new PropertyGroup[MMethod]("Methods")
-
-       # The inner classes.
-       var inner_classes = new PropertyGroup[MInnerClass]("Inner classes")
-
-       # All the groups.
-       #
-       # Sorted in the order they are displayed to the user.
-       var groups: SequenceRead[PropertyGroup[MProperty]] = [
-                       virtual_types,
-                       constructors,
-                       attributes,
-                       methods,
-                       inner_classes: PropertyGroup[MProperty]]
-
-       # Add each the specified property to the appropriate list.
-       init with_elements(properties: Collection[MProperty]) do add_all(properties)
-
-       # Add the specified property to the appropriate list.
-       fun add(property: MProperty) do
-               if property isa MMethod then
-                       if property.is_init then
-                               constructors.add property
-                       else
-                               methods.add property
-                       end
-               else if property isa MVirtualTypeProp then
-                       virtual_types.add property
-               else if property isa MAttribute then
-                       attributes.add property
-               else if property isa MInnerClass then
-                       inner_classes.add property
-               else
-                       abort
-               end
-       end
-
-       # Add each the specified property to the appropriate list.
-       fun add_all(properties: Collection[MProperty]) do
-               for p in properties do add(p)
-       end
-
-       # Sort each group with the specified comparator.
-       fun sort_groups(comparator: Comparator) do
-               for g in groups do comparator.sort(g)
-       end
-end
-
-# An ordered list of properties of the same kind.
-class PropertyGroup[E: MProperty]
-       super Array[E]
-
-       # The title of the group, as displayed to the user.
-       var title: String
-end
-
-redef class MEntity
-       # ID used as a unique ID and in file names.
-       #
-       # **Must** match the following (POSIX ERE) regular expression:
-       #
-       # ~~~POSIX ERE
-       # ^[A-Za-z_][A-Za-z0-9._-]*$
-       # ~~~
-       #
-       # That way, the ID is always a valid URI component and a valid XML name.
-       fun nitdoc_id: String do return full_name.to_cmangle
-
-       # Name displayed in console for debug and tests.
-       fun nitdoc_name: String do return name.html_escape
-end
-
-redef class MModule
-
-       # Avoid id conflict with group
-       redef fun nitdoc_id do
-               var mgroup = self.mgroup
-               if mgroup == null then return super
-               return "{mgroup.full_name}::{full_name}".to_cmangle
-       end
-end
-
-redef class MClassDef
-       redef fun nitdoc_name do return mclass.nitdoc_name
-end
-
-redef class MPropDef
-       redef fun nitdoc_name do return mproperty.nitdoc_name
-end
diff --git a/src/doc/doc_commands.nit b/src/doc/doc_commands.nit
deleted file mode 100644 (file)
index 208738b..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-# 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.
-
-# Parsing of commands understood by documentation tools.
-#
-# This can be through:
-# * `nitx` commands like `code: MEntity::name`
-# * `nitdoc` wikilinks like `[[doc: MEntity::name]]`
-module doc_commands
-
-#
-class DocCommandParser
-
-       # List of allowed command names for this parser
-       var allowed_commands: Array[String] = [ "doc", "list", "param", "return",
-               "new", "call", "code", "graph"] is writable
-
-       # Parse `string` as a DocCommand
-       #
-       # Returns `null` if the string cannot be parsed.
-       #
-       # ~~~
-       # var parser = new DocCommandParser
-       #
-       # var command = parser.parse("doc: core::Array")
-       # assert command isa CommentCommand
-       # assert command.arg == "core::Array"
-       #
-       # command = parser.parse(":") # syntax error
-       # assert command == null
-       # assert parser.errors.not_empty
-       # ~~~
-       fun parse(string: String): nullable DocCommand do
-               var pos = 0
-               var tmp = new FlatBuffer
-               errors.clear
-
-               # Parse command name
-               pos = string.read_until(tmp, pos, ':')
-               var name = tmp.write_to_string.trim
-
-               # Check allowed commands
-               if name.is_empty then
-                       error("empty command name", 0)
-                       return null
-               end
-               if not allowed_commands.has(name) then
-                       error("unknown command name", 0)
-                       return null
-               end
-
-               # Build the command
-               var command = new_command(name, string)
-               if command == null then
-                       error("unknown command name", 0)
-                       return null
-               end
-
-               # Parse the argument
-               tmp.clear
-               pos = string.read_until(tmp, pos + 1, '|')
-               var arg = tmp.write_to_string.trim
-               if arg.is_empty then
-                       error("empty command arg", pos)
-                       return null
-               end
-               command.arg = arg
-
-               # Parse command options
-               while pos < string.length do
-                       # Parse option name
-                       tmp.clear
-                       pos = string.read_until(tmp, pos + 1, ':', ',')
-                       var oname = tmp.write_to_string.trim
-                       var oval = ""
-                       if oname.is_empty then break
-                       # Parse option value
-                       if pos < string.length and string[pos] == ':' then
-                               tmp.clear
-                               pos = string.read_until(tmp, pos + 1, ',')
-                               oval = tmp.write_to_string.trim
-                       end
-                       command.opts[oname] = oval
-                       # TODO Check options
-               end
-
-               return command
-       end
-
-       # Init a new DocCommand from its `name`
-       #
-       # You must redefine this method to add new custom commands.
-       fun new_command(name, string: String): nullable DocCommand do
-               if name == "doc" then return new CommentCommand(string)
-               if name == "list" then return new ListCommand(string)
-               if name == "param" then return new ParamCommand(string)
-               if name == "return" then return new ReturnCommand(string)
-               if name == "new" then return new NewCommand(string)
-               if name == "call" then return new CallCommand(string)
-               if name == "code" then return new CodeCommand(string)
-               if name == "graph" then return new GraphCommand(string)
-               return null
-       end
-
-       # Errors and warnings from last call to `parse`
-       var errors = new Array[DocMessage]
-
-       # Generate an error
-       fun error(message: String, col: nullable Int) do
-               errors.add new DocMessage(1, message, col)
-       end
-
-       # Generate a warning
-       fun warning(message: String, col: nullable Int) do
-               errors.add new DocMessage(2, message, col)
-       end
-end
-
-# A message generated by the DocCommandParser
-class DocMessage
-
-       # Message severity
-       #
-       # 1- Error
-       # 2- Warning
-       var level: Int
-
-       # Message explanatory string
-       var message: String
-
-       # Related column in original string if any
-       var col: nullable Int
-
-       redef fun to_s do
-               var str = new FlatBuffer
-               if level == 1 then
-                       str.append "Error: "
-               else
-                       str.append "Warning: "
-               end
-               str.append message
-               var col = self.col
-               if col != null then
-                       str.append " (col: {col})"
-               end
-               return str.write_to_string
-       end
-end
-
-redef class Text
-       # Read `self` as raw text until `nend` and append it to the `out` buffer.
-       private fun read_until(out: FlatBuffer, start: Int, nend: Char...): Int do
-               var pos = start
-               while pos < length do
-                       var c = self[pos]
-                       var end_reached = false
-                       for n in nend do
-                               if c == n then
-                                       end_reached = true
-                                       break
-                               end
-                       end
-                       if end_reached then break
-                       out.add c
-                       pos += 1
-               end
-               return pos
-       end
-end
-
-# A command aimed at a documentation tool like `nitdoc` or `nitx`.
-#
-# `DocCommand` are generally of the form `command: arg | opt1: val1, opt2: val2`.
-abstract class DocCommand
-
-       # Original command string.
-       var string: String
-
-       # Command name.
-       var name: String is noinit
-
-       # Command arguments.
-       var arg: String is noinit, writable
-
-       # Command options.
-       var opts = new HashMap[String, String] is writable
-
-       redef fun to_s do
-               if opts.is_empty then
-                       return "{name}: {arg}"
-               end
-               return "{name}: {arg} | {opts.join(", ", ": ")}"
-       end
-end
-
-# A `DocCommand` that includes the documentation article of a `MEntity`.
-#
-# Syntax: `doc: MEntity::name`.
-class CommentCommand
-       super DocCommand
-
-       redef var name = "doc"
-end
-
-# A `DocCommand` that includes a list of something.
-#
-# Syntax: `list:kind: <arg>`.
-class ListCommand
-       super DocCommand
-
-       redef var name = "list"
-end
-
-# A `DocCommand` that includes the list of methods tanking a `MType` as parameter.
-#
-# Syntax: `param: MType`.
-class ParamCommand
-       super DocCommand
-
-       redef var name = "param"
-end
-
-# A `DocCommand` that includes the list of methods returning a `MType` as parameter.
-#
-# Syntax: `return: MType`.
-class ReturnCommand
-       super DocCommand
-
-       redef var name = "return"
-end
-
-# A `DocCommand` that includes the list of methods creating new instances of a specific `MType`
-#
-# Syntax: `new: MType`.
-class NewCommand
-       super DocCommand
-
-       redef var name = "new"
-end
-
-# A `DocCommand` that includes the list of methods calling a specific `MProperty`.
-#
-# Syntax: `call: MEntity::name`.
-class CallCommand
-       super DocCommand
-
-       redef var name = "call"
-end
-
-# A `DocCommand` that includes the source code of a `MEntity`.
-#
-# Syntax:
-# * `code: MEntity::name`
-# * `./src/file.nit` to include source code from a file.
-# * `./src/file.nit:1,2--3,4` to select code between positions.
-class CodeCommand
-       super DocCommand
-
-       redef var name = "code"
-end
-
-# A `DocCommand` that display an graph for a `MEntity`.
-#
-# Syntax:
-# * `graph: MEntity::name`
-class GraphCommand
-       super DocCommand
-
-       redef var name = "graph"
-end
diff --git a/src/doc/doc_down.nit b/src/doc/doc_down.nit
deleted file mode 100644 (file)
index 7bb330b..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-# 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.
-
-# Handle markdown formatting in Nit comments.
-module doc_down
-
-import markdown
-import htmlight
-private import parser_util
-
-redef class MDoc
-
-       # Synopsis HTML escaped.
-       var synopsis: String is lazy do return content.first.html_escape
-
-       # Comment without synopsis HTML escaped
-       var comment: String is lazy do
-               var lines = content.to_a
-               if not lines.is_empty then lines.shift
-               return lines.join("\n")
-       end
-
-       # Full comment HTML escaped.
-       var documentation: String is lazy do return content.join("\n")
-
-       private var markdown_proc: MarkdownProcessor is lazy, writable do
-               return original_mentity.as(not null).model.nitdoc_md_processor
-       end
-
-       private var inline_proc: MarkdownProcessor is lazy, writable do
-               return original_mentity.as(not null).model.nitdoc_inline_processor
-       end
-
-       # Renders the synopsis as a HTML comment block.
-       var html_synopsis: Writable is lazy do
-               var res = new Template
-               var syn = inline_proc.process(content.first)
-               res.add "<span class=\"synopsys nitdoc\">{syn}</span>"
-               return res
-       end
-
-       # Renders the synopsis as a HTML comment block.
-       var md_synopsis: Writable is lazy do
-               if content.is_empty then return ""
-               return content.first
-       end
-
-       # Renders the comment without the synopsis as a HTML comment block.
-       var html_comment: Writable is lazy do
-               var lines = content.to_a
-               if not lines.is_empty then lines.shift
-               return lines_to_html(lines)
-       end
-
-       #
-       var md_comment: Writable is lazy do
-               if content.is_empty then return ""
-               var lines = content.to_a
-               lines.shift
-               return lines.join("\n")
-       end
-
-       # Renders the synopsis and the comment as a HTML comment block.
-       var html_documentation: Writable is lazy do return lines_to_html(content.to_a)
-
-       # Renders the synopsis and the comment as a HTML comment block.
-       var md_documentation: Writable is lazy do return lines_to_md(content.to_a)
-
-       # Renders markdown line as a HTML comment block.
-       private fun lines_to_html(lines: Array[String]): Writable do
-               var res = new Template
-               var decorator = markdown_proc.decorator.as(NitdocDecorator)
-               decorator.current_mdoc = self
-               res.add "<div class=\"nitdoc\">"
-               # do not use DocUnit as synopsys
-               if not lines.is_empty then
-                       if not lines.first.has_prefix("    ") and
-                          not lines.first.has_prefix("\t") then
-                               # parse synopsys
-                               var syn = inline_proc.process(lines.shift)
-                               res.add "<h1 class=\"synopsys\">{syn}</h1>"
-                       end
-               end
-               # check for annotations
-               for i in [0 .. lines.length[ do
-                       var line = lines[i]
-                       if line.to_upper.has_prefix("ENSURE") or line.to_upper.has_prefix("REQUIRE") then
-                               var html = inline_proc.process(line)
-                               lines[i] = "<p class=\"contract\">{html}</p>"
-                       else if line.to_upper.has_prefix("TODO") or line.to_upper.has_prefix("FIXME") then
-                               var html = inline_proc.process(line)
-                               lines[i] = "<p class=\"todo\">{html}</p>"
-                       end
-               end
-               # add other lines
-               res.add markdown_proc.process(lines.join("\n"))
-               res.add "</div>"
-               decorator.current_mdoc = null
-               return res
-       end
-
-       private fun lines_to_md(lines: Array[String]): Writable do
-               var res = new Template
-               if not lines.is_empty then
-                       var syn = lines.first
-                       if not syn.has_prefix("    ") and not syn.has_prefix("\t") and
-                         not syn.trim.has_prefix("#") then
-                               lines.shift
-                               res.add "# {syn}\n"
-                       end
-               end
-               res.add lines.join("\n")
-               return res
-       end
-end
-
-# The specific markdown decorator used internally to process MDoc object.
-#
-# You should use the various methods of `MDoc` like `MDoc::html_documentation`
-#
-# The class is public so specific behavior can be plugged on it.
-class NitdocDecorator
-       super HTMLDecorator
-
-       private var toolcontext = new ToolContext
-
-       # The currently processed mdoc.
-       #
-       # Unfortunately, this seems to be the simpler way to get the currently processed `MDoc` object.
-       var current_mdoc: nullable MDoc = null
-
-       redef fun add_code(v, block) do
-               var meta = block.meta or else "nit"
-
-               # Do not try to highlight non-nit code.
-               if meta != "nit" and meta != "nitish" then
-                       v.add "<pre class=\"{meta}\"><code>"
-                       v.emit_in block
-                       v.add "</code></pre>\n"
-                       return
-               end
-               # Try to parse code
-               var code = block.raw_content
-               var ast = toolcontext.parse_something(code)
-               if ast isa AError then
-                       v.add "<pre class=\"{meta}\"><code>"
-                       v.emit_in block
-                       v.add "</code></pre>\n"
-                       return
-               end
-               v.add "<pre class=\"nitcode\"><code>"
-               var hl = new HtmlightVisitor
-               hl.line_id_prefix = ""
-               hl.highlight_node(ast)
-               v.add(hl.html)
-               v.add "</code></pre>\n"
-       end
-
-       redef fun add_span_code(v, text, from, to) do
-               # Try to parse it
-               var code = code_from_text(text, from, to)
-               var ast = toolcontext.parse_something(code)
-
-               if ast isa AError then
-                       v.add "<code class=\"rawcode\">"
-                       append_code(v, text, from, to)
-               else
-                       v.add "<code class=\"nitcode\">"
-                       var hl = new HtmlightVisitor
-                       hl.line_id_prefix = ""
-                       hl.highlight_node(ast)
-                       v.add(hl.html)
-               end
-               v.add "</code>"
-       end
-
-       private fun code_from_text(buffer: Text, from, to: Int): String do
-               var out = new FlatBuffer
-               for i in [from..to[ do out.add buffer[i]
-               return out.write_to_string
-       end
-end
-
-# Decorator for span elements.
-#
-# Because inline comments can appear as span elements,
-# InlineDecorator do not decorate things like paragraphs or headers.
-private class InlineDecorator
-       super NitdocDecorator
-
-       redef fun add_paragraph(v, block) do
-               v.emit_in block
-       end
-
-       redef fun add_headline(v, block) do
-               v.emit_in block
-       end
-
-       redef fun add_code(v, block) do
-               # Try to parse code
-               var ast = toolcontext.parse_something(block.block.text.to_s)
-               if ast isa AError then
-                       v.add "<code>"
-                       v.emit_in block
-                       v.add "</code>"
-                       return
-               end
-               v.add "<code class=\"nitcode\">"
-               var hl = new HtmlightVisitor
-               hl.highlight_node(ast)
-               v.add(hl.html)
-               v.add "</code>"
-       end
-end
-
-redef class Model
-       # Get a markdown processor for Nitdoc comments.
-       var nitdoc_md_processor: MarkdownProcessor is lazy, writable do
-               var proc = new MarkdownProcessor
-               proc.decorator = new NitdocDecorator
-               return proc
-       end
-
-       # Get a markdown inline processor for Nitdoc comments.
-       #
-       # This processor is specificaly designed to inlinable doc elements like synopsys.
-       var nitdoc_inline_processor: MarkdownProcessor is lazy, writable do
-               var proc = new MarkdownProcessor
-               proc.decorator = new InlineDecorator
-               return proc
-       end
-end
diff --git a/src/doc/doc_phases/doc_concerns.nit b/src/doc/doc_phases/doc_concerns.nit
deleted file mode 100644 (file)
index a84adb2..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-# 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.
-
-# Concerns computation.
-module doc_concerns
-
-import doc_pages
-import model::model_collect
-
-# ConcernsPhase computes the ConcernsTree used for each page layout.
-class ConcernsPhase
-       super DocPhase
-
-       # Populates the given DocModel.
-       redef fun apply do
-               for page in doc.pages.values do page.build_concerns(self)
-       end
-end
-
-redef class DocPage
-
-       # Build the `concerns` tree for this page.
-       #
-       # Since only `MEntityPage`, this method is a no-op for everything else.
-       private fun build_concerns(v: ConcernsPhase) do end
-end
-
-redef class MEntityPage
-
-       # Concerns to display in this page.
-       var concerns: nullable ConcernsTree = null
-end
-
-# TODO ConcernsTrees are a PITA, following redef should not be needed here...
-# The bad, so baaaadddd, ConcernsTree interface induces a lot of useless code
-# in all phases.
-
-redef class MGroupPage
-
-       # Introduced classes in `mentity` that should appear in this page.
-       var intros = new HashSet[MClass]
-
-       # Refined classes in `mentity` that should appear in this page.
-       var redefs = new HashSet[MClass]
-
-       redef fun build_concerns(v) do
-               var doc = v.doc
-               var mmodules = new HashSet[MModule]
-               for mmodule in mentity.mmodules do
-                       if doc.mmodules.has(mmodule) then mmodules.add mmodule
-                       # collect mclasses
-                       for mclass in mmodule.intro_mclasses do
-                               if doc.mclasses.has(mclass) then intros.add mclass
-                       end
-                       for mclass in mmodule.collect_redef_mclasses(v.doc) do
-                               if doc.mclasses.has(mclass) then redefs.add mclass
-                       end
-               end
-               concerns = doc.model.concerns_tree(mmodules)
-       end
-end
-
-redef class MModulePage
-
-       # MClasses defined in `mentity` to display in this page.
-       var mclasses = new HashSet[MClass]
-
-       # MClassDefs located in `mentity` to display in this page.
-       var mclassdefs = new HashSet[MClassDef]
-
-       redef fun build_concerns(v) do
-               var doc = v.doc
-               # extract mclassdefs in mmodule
-               for mclassdef in mentity.mclassdefs do
-                       if doc.mclassdefs.has(mclassdef) then mclassdefs.add mclassdef
-               end
-               # extract mclasses in mmodule
-               for mclassdef in mclassdefs do
-                       var mclass = mclassdef.mclass
-                       if doc.mclasses.has(mclass) then mclasses.add mclass
-               end
-               # extract concerns
-               var mods = new HashSet[MModule]
-               for mclass in mclasses do
-                       var mod = mclass.intro_mmodule
-                       if doc.mmodules.has(mod) then mods.add mod
-               end
-               concerns = doc.model.concerns_tree(mods)
-       end
-end
-
-redef class MClassPage
-
-       # MClassDefs to display in this page.
-       var mclassdefs = new HashSet[MClassDef]
-
-       # MPropdefs to display in this page.
-       var mpropdefs = new HashSet[MPropDef]
-
-       redef fun build_concerns(v) do
-               var doc = v.doc
-               # collect mclassdefs
-               for mclassdef in mentity.mclassdefs do
-                       if doc.mclassdefs.has(mclassdef) then mclassdefs.add mclassdef
-               end
-               # collect mpropdefs
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if doc.mpropdefs.has(mpropdef) then mpropdefs.add mpropdef
-                       end
-               end
-               # collect concerns
-               var mods = new HashSet[MModule]
-               for mpropdef in mpropdefs do
-                       var mod = mpropdef.mclassdef.mmodule
-                       if doc.mmodules.has(mod) then mods.add mod
-               end
-               concerns = doc.model.concerns_tree(mods)
-       end
-end
-
-redef class MPropertyPage
-
-       # MPropdefs to display in this page.
-       var mpropdefs = new HashSet[MPropDef]
-
-       redef fun build_concerns(v) do
-               var doc = v.doc
-               # collect mpropdefs
-               for mpropdef in mentity.mpropdefs do
-                       # FIXME diff hack
-                       if mpropdef.is_intro then continue
-                       if doc.mpropdefs.has(mpropdef) then mpropdefs.add mpropdef
-               end
-               # collect concerns
-               var mods = new HashSet[MModule]
-               for mpropdef in mpropdefs do
-                       var mod = mpropdef.mclassdef.mmodule
-                       if doc.mmodules.has(mod) then mods.add mod
-               end
-               concerns = doc.model.concerns_tree(mods)
-       end
-end
diff --git a/src/doc/doc_phases/doc_graphs.nit b/src/doc/doc_phases/doc_graphs.nit
deleted file mode 100644 (file)
index c559e80..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-# 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_structure
-import doc_poset
-import html_templates::html_model # FIXME maybe this phase should depend on `html_render`
-
-redef class ToolContext
-
-       # Do not generate `graphviz` diagrams.
-       var opt_nodot = new OptionBool("Do not generate graphs 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.values do
-                       var article = page.build_graph(self, doc)
-                       if article == null then continue
-                       # FIXME avoid diff
-                       # page.root.add article
-                       article.parent = page.root.children.first.children[1]
-                       page.root.children.first.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("{mentity.nitdoc_id}.graph", "Importation Graph", 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("{mentity.nitdoc_id}.graph", "Inheritance Graph", 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 DocArticle
-
-       # Graph ID (used for outputing file with names).
-       var graph_id: String
-
-       # Dot script of the graph.
-       var dot: Text
-
-       redef var is_hidden = false
-       redef var is_toc_hidden = true
-end
diff --git a/src/doc/doc_phases/doc_hierarchies.nit b/src/doc/doc_phases/doc_hierarchies.nit
deleted file mode 100644 (file)
index fa9de2d..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-# 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.
-
-# Computes importation and class hierarchy lists.
-module doc_hierarchies
-
-import doc_structure
-import doc_poset
-
-# Insert inheritance / importation lists in the page.
-class InheritanceListsPhase
-       super DocPhase
-
-       # Used to sort list by name.
-       var name_sorter = new MEntityNameSorter
-
-       redef fun apply do
-               for page in doc.pages.values do
-                       if page isa MEntityPage then page.build_inh_list(self, doc)
-               end
-       end
-end
-
-redef class MEntityPage
-
-       # Build importation / inheritance list for this page.
-       fun build_inh_list(v: InheritanceListsPhase, doc: DocModel) do end
-end
-
-redef class MModulePage
-       redef fun build_inh_list(v, doc) do
-               var id = mentity.nitdoc_id
-               var section = new TabbedGroup("{id}.importation", "Dependencies")
-               var group = new PanelGroup("list.group", "List")
-               var imports = self.imports.to_a
-               v.name_sorter.sort(imports)
-               group.add_child new MEntitiesListArticle("{id}.imports", "Imports", imports)
-               var clients = self.clients.to_a
-               v.name_sorter.sort(clients)
-               group.add_child new MEntitiesListArticle("{id}.clients", "Clients", clients)
-               section.add_child group
-               section.parent = root.children.first
-               root.children.first.children.insert(section, 1)
-       end
-end
-
-redef class MClassPage
-       redef fun build_inh_list(v, doc) do
-               var id = mentity.nitdoc_id
-               var section = new TabbedGroup("{id}.inheritance", "Inheritance")
-               var group = new PanelGroup("list.group", "List")
-               var parents = self.parents.to_a
-               v.name_sorter.sort(parents)
-               group.add_child new MEntitiesListArticle("{id}.parents", "Parents", parents)
-               var ancestors = self.ancestors.to_a
-               v.name_sorter.sort(ancestors)
-               group.add_child new MEntitiesListArticle("{id}.ancestors", "Ancestors", ancestors)
-               var children = self.children.to_a
-               v.name_sorter.sort(children)
-               group.add_child new MEntitiesListArticle("{id}.children", "Children", children)
-               var descendants = self.descendants.to_a
-               v.name_sorter.sort(descendants)
-               group.add_child new MEntitiesListArticle("{id}.descendants", "Descendants", descendants)
-               section.add_child group
-               section.parent = root.children.first
-               root.children.first.children.insert(section, 1)
-       end
-end
diff --git a/src/doc/doc_phases/doc_html.nit b/src/doc/doc_phases/doc_html.nit
deleted file mode 100644 (file)
index 20cd2f4..0000000
+++ /dev/null
@@ -1,631 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Render the DocModel pages as HTML pages.
-#
-# FIXME this module is all f*cked up to maintain compatibility with
-# the original `doc_templates` and `doc_model` modules.
-# This will change in further refactorings.
-module doc_html
-
-import doc_structure
-import doc_hierarchies
-import doc_intros_redefs
-import doc_graphs
-import html_templates
-
-redef class ToolContext
-
-       # File pattern used to link documentation to source code.
-       var opt_source = new OptionString("Format to link source code (%f for filename, " +
-               "%l for first line, %L for last line)", "--source")
-
-       # Use a shareurl instead of copy shared files.
-       #
-       # This is usefull if you don't want to store the Nitdoc templates with your
-       # documentation.
-       var opt_shareurl = new OptionString("Use shareurl instead of copy shared files", "--shareurl")
-
-       # Use a custom title for the homepage.
-       var opt_custom_title = new OptionString("Custom title for homepage", "--custom-title")
-
-       # Display a custom brand or logo in the documentation top menu.
-       var opt_custom_brand = new OptionString("Custom link to external site", "--custom-brand")
-
-       # Display a custom introduction text before the packages overview.
-       var opt_custom_intro = new OptionString("Custom intro text for homepage", "--custom-overview-text")
-       # Display a custom footer on each documentation page.
-       #
-       # Generally used to display the documentation or product version.
-       var opt_custom_footer = new OptionString("Custom footer text", "--custom-footer-text")
-
-       # Piwik tracker URL.
-       #
-       # If you want to monitor your visitors.
-       var opt_piwik_tracker = new OptionString("Piwik tracker URL (ex: `nitlanguage.org/piwik/`)", "--piwik-tracker")
-
-       # Piwik tracker site id.
-       var opt_piwik_site_id = new OptionString("Piwik site ID", "--piwik-site-id")
-
-       # These options are not currently used in Nitdoc.
-
-       # FIXME redo the plugin
-       var opt_github_upstream = new OptionString("Git branch where edited commits will be pulled into (ex: user:repo:branch)", "--github-upstream")
-       # FIXME redo the plugin
-       var opt_github_base_sha1 = new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
-       # FIXME redo the plugin
-       var opt_github_gitdir = new OptionString("Git working directory used to resolve path name (ex: /home/me/mypackage/)", "--github-gitdir")
-
-       # Do not produce HTML files
-       var opt_no_render = new OptionBool("Do not render HTML files", "--no-render")
-
-       redef init do
-               super
-
-               option_context.add_option(
-                       opt_source, opt_share_dir, opt_shareurl, opt_custom_title,
-                       opt_custom_footer, opt_custom_intro, opt_custom_brand,
-                       opt_github_upstream, opt_github_base_sha1, opt_github_gitdir,
-                       opt_piwik_tracker, opt_piwik_site_id,
-                       opt_no_render)
-       end
-
-       redef fun process_options(args) do
-               super
-               var upstream = opt_github_upstream
-               var base_sha = opt_github_base_sha1
-               var git_dir = opt_github_gitdir
-               var opts = [upstream.value, base_sha.value, git_dir.value]
-               if not opts.has_only(null) and opts.has(null) then
-                       print "Option Error: options {upstream.names.first}, " +
-                               "{base_sha.names.first} and {git_dir.names.first} " +
-                               "are required to enable the GitHub plugin"
-                       exit 1
-               end
-       end
-end
-
-# Render the Nitdoc as a HTML website.
-class RenderHTMLPhase
-       super DocPhase
-
-       # Used to sort sidebar elements by name.
-       var name_sorter = new MEntityNameSorter
-
-       redef fun apply do
-               if ctx.opt_no_render.value then return
-               init_output_dir
-               for page in doc.pages.values do
-                       page.render(self, doc).write_to_file("{ctx.output_dir.to_s}/{page.html_url}")
-               end
-       end
-
-       # Creates the output directory and imports assets files form `resources/`.
-       fun init_output_dir do
-               # create destination dir if it's necessary
-               var output_dir = ctx.output_dir
-               if not output_dir.file_exists then output_dir.mkdir
-               # locate share dir
-               var sharedir = ctx.share_dir / "nitdoc"
-               # copy shared files
-               if ctx.opt_shareurl.value == null then
-                       sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
-               else
-                       sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
-               end
-
-       end
-
-       # Returns a HTML link for a given `location`.
-       fun html_source_link(location: nullable Location): nullable String
-       do
-               if location == null then return null
-               var source = ctx.opt_source.value
-               if source == null then
-                       var url = location.file.filename.simplify_path
-                       return "<a target='_blank' title='Show source' href=\"{url.html_escape}\">View Source</a>"
-               end
-               # THIS IS JUST UGLY ! (but there is no replace yet)
-               var x = source.split_with("%f")
-               source = x.join(location.file.filename.simplify_path)
-               x = source.split_with("%l")
-               source = x.join(location.line_start.to_s)
-               x = source.split_with("%L")
-               source = x.join(location.line_end.to_s)
-               source = source.simplify_path
-               return "<a target='_blank' title='Show source' href=\"{source.to_s.html_escape}\">View Source</a>"
-       end
-end
-
-redef class DocPage
-
-       # Render the page as a html template.
-       private fun render(v: RenderHTMLPhase, doc: DocModel): Writable do
-               var shareurl = "."
-               if v.ctx.opt_shareurl.value != null then
-                       shareurl = v.ctx.opt_shareurl.value.as(not null)
-               end
-
-               # init page options
-               self.shareurl = shareurl
-               self.footer = v.ctx.opt_custom_footer.value
-               self.body_attrs.add(new TagAttribute("data-bootstrap-share", shareurl))
-
-               # build page
-               init_title(v, doc)
-               init_topmenu(v, doc)
-               init_content(v, doc)
-               init_sidebar(v, doc)
-
-               # piwik tracking
-               var tracker_url = v.ctx.opt_piwik_tracker.value
-               var site_id = v.ctx.opt_piwik_site_id.value
-               if tracker_url != null and site_id != null then
-                       self.scripts.add new TplPiwikScript(tracker_url, site_id)
-               end
-               return self
-       end
-
-       # FIXME diff hack
-       # all properties below are roughly copied from `doc_pages`
-
-       # Build page title string
-       fun init_title(v: RenderHTMLPhase, doc: DocModel) do end
-
-       # Build top menu template if any.
-       fun init_topmenu(v: RenderHTMLPhase, doc: DocModel) do
-               topmenu = new DocTopMenu
-               topmenu.brand = v.ctx.opt_custom_brand.value
-               var title = "Overview"
-               if v.ctx.opt_custom_title.value != null then
-                       title = v.ctx.opt_custom_title.value.to_s
-               end
-               topmenu.add_li new ListItem(new Link("index.html", title))
-               topmenu.add_li new ListItem(new Link("search.html", "Index"))
-               topmenu.active_item = topmenu.items.first
-       end
-
-       # Build page sidebar if any.
-       fun init_sidebar(v: RenderHTMLPhase, doc: DocModel) do
-               sidebar = new DocSideBar
-               sidebar.boxes.add new DocSideBox("Summary", html_toc)
-       end
-
-       # Build page content template.
-       fun init_content(v: RenderHTMLPhase, doc: DocModel) do
-               root.init_html_render(v, doc, self)
-       end
-end
-
-redef class OverviewPage
-       redef var html_url = "index.html"
-
-       redef fun init_title(v, doc) do
-               title = "Overview"
-               if v.ctx.opt_custom_title.value != null then
-                       title = v.ctx.opt_custom_title.value.to_s
-               end
-       end
-end
-
-redef class SearchPage
-       redef var html_url = "search.html"
-       redef fun init_title(v, doc) do title = "Index"
-
-       redef fun init_topmenu(v, doc) do
-               super
-               topmenu.active_item = topmenu.items.last
-       end
-
-       redef fun init_sidebar(v, doc) do end
-end
-
-redef class MEntityPage
-       redef var html_url is lazy do
-               if mentity isa MGroup and mentity.mdoc != null then
-                       return "api_{mentity.nitdoc_url}"
-               end
-               return mentity.nitdoc_url
-       end
-
-       redef fun init_title(v, doc) do title = mentity.html_name
-end
-
-# FIXME all clases below are roughly copied from `doc_pages` and adapted to new
-# doc phases. This is to preserve the compatibility with the current
-# `doc_templates` module.
-
-redef class ReadmePage
-       redef var html_url is lazy do return mentity.nitdoc_url
-
-       redef fun init_topmenu(v, doc) do
-               super
-               var mpackage = mentity.mpackage
-               if not mentity.is_root then
-                       topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
-               end
-               topmenu.add_li new ListItem(new Link(html_url, mpackage.html_name))
-               topmenu.active_item = topmenu.items.last
-       end
-
-       redef fun init_sidebar(v, doc) do
-               super
-               var api_lnk = """<a href="api_{{{mentity.nitdoc_url}}}">Go to API</a>"""
-               sidebar.boxes.unshift new DocSideBox(api_lnk, "")
-       end
-end
-
-redef class MGroupPage
-       redef fun init_topmenu(v, doc) do
-               super
-               var mpackage = mentity.mpackage
-               if not mentity.is_root then
-                       topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
-               end
-               topmenu.add_li new ListItem(new Link(html_url, mpackage.html_name))
-               topmenu.active_item = topmenu.items.last
-       end
-
-       redef fun init_sidebar(v, doc) do
-               super
-               # README link
-               if mentity.mdoc != null then
-                       var doc_lnk = """<a href="{{{mentity.nitdoc_url}}}">Go to README</a>"""
-                       sidebar.boxes.unshift new DocSideBox(doc_lnk, "")
-               end
-               # MClasses list
-               var mclasses = new HashSet[MClass]
-               mclasses.add_all intros
-               mclasses.add_all redefs
-               if mclasses.is_empty then return
-               var list = new UnorderedList
-               list.css_classes.add "list-unstyled list-labeled"
-               var sorted = mclasses.to_a
-               v.name_sorter.sort(sorted)
-               for mclass in sorted do
-                       list.add_li tpl_sidebar_item(mclass)
-               end
-               sidebar.boxes.add new DocSideBox("All classes", list)
-               sidebar.boxes.last.is_open = false
-       end
-
-       private fun tpl_sidebar_item(def: MClass): ListItem do
-               var classes = def.intro.css_classes
-               if intros.has(def) then
-                       classes.add "intro"
-               else
-                       classes.add "redef"
-               end
-               var lnk = new Template
-               lnk.add new DocHTMLLabel.with_classes(classes)
-               lnk.add def.html_link
-               return new ListItem(lnk)
-       end
-end
-
-redef class MModulePage
-       redef fun init_topmenu(v, doc) do
-               super
-               var mpackage = mentity.mpackage
-               if mpackage != null then
-                       topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
-               end
-               topmenu.add_li new ListItem(new Link(mentity.nitdoc_url, mentity.html_name))
-               topmenu.active_item = topmenu.items.last
-       end
-
-       # Class list to display in sidebar
-       redef fun init_sidebar(v, doc) do
-               # TODO filter here?
-               super
-               var mclasses = new HashSet[MClass]
-               mclasses.add_all mentity.collect_intro_mclasses(v.doc)
-               mclasses.add_all mentity.collect_redef_mclasses(v.doc)
-               if mclasses.is_empty then return
-               var list = new UnorderedList
-               list.css_classes.add "list-unstyled list-labeled"
-
-               var sorted = mclasses.to_a
-               v.name_sorter.sort(sorted)
-               for mclass in sorted do
-                       list.add_li tpl_sidebar_item(mclass)
-               end
-               sidebar.boxes.add new DocSideBox("All classes", list)
-               sidebar.boxes.last.is_open = false
-       end
-
-       private fun tpl_sidebar_item(def: MClass): ListItem do
-               var classes = def.intro.css_classes
-               if def.intro_mmodule == self.mentity then
-                       classes.add "intro"
-               else
-                       classes.add "redef"
-               end
-               var lnk = new Template
-               lnk.add new DocHTMLLabel.with_classes(classes)
-               lnk.add def.html_link
-               return new ListItem(lnk)
-       end
-end
-
-redef class MClassPage
-
-       redef fun init_topmenu(v, doc) do
-               super
-               var mpackage = mentity.intro_mmodule.mgroup.mpackage
-               topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
-               topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
-               topmenu.active_item = topmenu.items.last
-       end
-
-       redef fun init_sidebar(v, doc) do
-               super
-               var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops(v, doc))
-               var summary = new UnorderedList
-               summary.css_classes.add "list-unstyled"
-
-               by_kind.sort_groups(v.name_sorter)
-               for g in by_kind.groups do tpl_sidebar_list(g, summary)
-               sidebar.boxes.add new DocSideBox("All properties", summary)
-               sidebar.boxes.last.is_open = false
-       end
-
-       private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: UnorderedList) do
-               if mprops.is_empty then return
-               var list = new UnorderedList
-               list.css_classes.add "list-unstyled list-labeled"
-               for mprop in mprops do
-                       list.add_li tpl_sidebar_item(mprop)
-               end
-               var content = new Template
-               content.add mprops.title
-               content.add list
-               var li = new ListItem(content)
-               summary.add_li li
-       end
-
-       private fun tpl_sidebar_item(mprop: MProperty): ListItem do
-               var classes = mprop.intro.css_classes
-               if not mprop_is_local(mprop) then
-                       classes.add "inherit"
-                       var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
-                       var def_url = "{cls_url}#{mprop.nitdoc_id}.definition"
-                       var lnk = new Link(def_url, mprop.html_name)
-                       var mdoc = mprop.intro.mdoc_or_fallback
-                       if mdoc != null then lnk.title = mdoc.synopsis
-                       var item = new Template
-                       item.add new DocHTMLLabel.with_classes(classes)
-                       item.add lnk
-                       return new ListItem(item)
-               end
-               if mpropdefs.has(mprop.intro) then
-                       classes.add "intro"
-               else
-                       classes.add "redef"
-               end
-               var def = select_mpropdef(mprop)
-               var anc = def.html_link_to_anchor
-               anc.href = "#{def.nitdoc_id}.definition"
-               var lnk = new Template
-               lnk.add new DocHTMLLabel.with_classes(classes)
-               lnk.add anc
-               return new ListItem(lnk)
-       end
-
-       # Get the mpropdef contained in `self` page for a mprop.
-       #
-       # FIXME this method is used to translate a mprop into a mpropdefs for
-       # section linking. A better page structure should avoid this...
-       private fun select_mpropdef(mprop: MProperty): MPropDef do
-               for mclassdef in mentity.mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef.mproperty == mprop then return mpropdef
-                       end
-               end
-               abort # FIXME is there a case where the prop is not found?
-       end
-
-       private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
-               var res = new HashSet[MProperty]
-               var local = mentity.collect_local_mproperties(v.doc)
-               for mprop in mentity.collect_inherited_mproperties(v.doc) do
-                       if local.has(mprop) then continue
-                       #if mprop isa MMethod and mprop.is_init then continue
-                       if mprop.intro.mclassdef.mclass.name == "Object" and
-                               (mprop.visibility == protected_visibility or
-                               mprop.intro.mclassdef.mmodule.name != "kernel") then continue
-                       res.add mprop
-               end
-               res.add_all local
-               return res
-       end
-
-       private fun mprop_is_local(mprop: MProperty): Bool do
-               for mpropdef in mprop.mpropdefs do
-                       if self.mpropdefs.has(mpropdef) then return true
-               end
-               return false
-       end
-end
-
-redef class MPropertyPage
-       redef fun init_title(v, doc) do
-               title = "{mentity.html_name}{mentity.html_short_signature.write_to_string}"
-       end
-
-       redef fun init_topmenu(v, doc) do
-               super
-               var mmodule = mentity.intro_mclassdef.mmodule
-               var mpackage = mmodule.mgroup.mpackage
-               var mclass = mentity.intro_mclassdef.mclass
-               topmenu.add_li new ListItem(new Link(mpackage.nitdoc_url, mpackage.html_name))
-               topmenu.add_li new ListItem(new Link(mclass.nitdoc_url, mclass.html_name))
-               topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
-               topmenu.active_item = topmenu.items.last
-       end
-end
-
-redef class DocComposite
-       # Prepares the HTML rendering for this element.
-       #
-       # This visit is mainly used to set template attributes before rendering.
-       fun init_html_render(v: RenderHTMLPhase, doc: DocModel, page: DocPage) do
-               for child in children do child.init_html_render(v, doc, page)
-       end
-end
-
-# FIXME hideous hacks to avoid diff
-redef class MEntitySection
-       redef fun init_html_render(v, doc, page) do
-               if not page isa MEntityPage then return
-               var mentity = self.mentity
-               if mentity isa MGroup and mentity.is_root then
-                       html_title = mentity.mpackage.html_name
-                       html_subtitle = mentity.mpackage.html_declaration
-               else if mentity isa MProperty then
-                       var title = new Template
-                       title.add mentity.html_name
-                       title.add mentity.html_signature
-                       html_title = title
-                       html_subtitle = mentity.html_namespace
-                       html_toc_title = mentity.html_name
-               end
-               super
-       end
-end
-
-# FIXME hideous hacks to avoid diff
-redef class ConcernSection
-       redef fun init_html_render(v, doc, page) do
-               if not page isa MEntityPage then return
-               var mentity = self.mentity
-               if page isa MGroupPage then
-                       html_title = null
-                       html_toc_title = mentity.html_name
-                       is_toc_hidden = false
-               else if page.mentity isa MModule and mentity isa MModule then
-                       var title = new Template
-                       if mentity == page.mentity then
-                               title.add "in "
-                               html_toc_title = "in {mentity.html_name}"
-                       else
-                               title.add "from "
-                               html_toc_title = "from {mentity.html_name}"
-                       end
-                       title.add mentity.html_namespace
-                       html_title = title
-               else if (page.mentity isa MClass and mentity isa MModule) or
-                               (page.mentity isa MProperty and mentity isa MModule) then
-                       var title = new Template
-                       title.add "in "
-                       title.add mentity.html_namespace
-                       html_title = title
-                       html_toc_title = "in {mentity.html_name}"
-               end
-               super
-       end
-end
-
-# TODO redo showlink
-redef class IntroArticle
-       redef fun init_html_render(v, doc, page) do
-               var mentity = self.mentity
-               if mentity isa MModule then
-                       html_source_link = v.html_source_link(mentity.location)
-               else if mentity isa MClassDef then
-                       html_source_link = v.html_source_link(mentity.location)
-               else if mentity isa MPropDef then
-                       html_source_link = v.html_source_link(mentity.location)
-               end
-       end
-end
-
-# FIXME less hideous hacks...
-redef class DefinitionArticle
-       redef fun init_html_render(v, doc, page) do
-               var mentity = self.mentity
-               if mentity isa MPackage or mentity isa MModule then
-                       var title = new Template
-                       title.add mentity.html_icon
-                       title.add mentity.html_namespace
-                       html_title = title
-                       html_toc_title = mentity.html_name
-                       if mentity isa MModule then
-                               html_source_link = v.html_source_link(mentity.location)
-                       end
-               else if mentity isa MClassDef then
-                       var title = new Template
-                       title.add "in "
-                       title.add mentity.mmodule.html_namespace
-                       html_title = mentity.html_declaration
-                       html_subtitle = title
-                       html_toc_title = "in {mentity.html_name}"
-                       html_source_link = v.html_source_link(mentity.location)
-                       if page isa MEntityPage and mentity.is_intro and mentity.mmodule != page.mentity then
-                               is_short_comment = true
-                       end
-                       if page isa MModulePage then is_toc_hidden = true
-               else if mentity isa MPropDef then
-                       if page isa MClassPage then
-                               var title = new Template
-                               title.add mentity.html_icon
-                               title.add mentity.html_declaration
-                               html_title = title
-                               html_subtitle = mentity.html_namespace
-                               html_toc_title = mentity.html_name
-                       else
-                               var title = new Template
-                               title.add "in "
-                               title.add mentity.mclassdef.html_link
-                               html_title = title
-                               html_toc_title = "in {mentity.mclassdef.html_name}"
-                       end
-                       html_source_link = v.html_source_link(mentity.location)
-               end
-               if page isa MGroupPage and mentity isa MModule then
-                       is_toc_hidden = true
-               end
-               super
-       end
-end
-
-redef class HomeArticle
-       redef fun init_html_render(v, doc, page) do
-               if v.ctx.opt_custom_title.value != null then
-                       self.html_title = v.ctx.opt_custom_title.value.to_s
-                       self.html_toc_title = v.ctx.opt_custom_title.value.to_s
-               end
-               self.content = v.ctx.opt_custom_intro.value
-               super
-       end
-end
-
-redef class GraphArticle
-       redef fun init_html_render(v, doc, page) do
-               var path = v.ctx.output_dir / graph_id
-               var file = new FileWriter.open("{path}.dot")
-               file.write(dot)
-               file.close
-               var proc = new ProcessReader("dot", "-Tsvg", "-Tcmapx", "{path}.dot")
-               var svg = new Buffer
-               var i = 0
-               while not proc.eof do
-                       i += 1
-                       if i < 6 then continue # skip dot default header
-                       svg.append proc.read_line
-               end
-               proc.close
-               self.svg = svg.write_to_string
-       end
-end
diff --git a/src/doc/doc_phases/doc_indexing.nit b/src/doc/doc_phases/doc_indexing.nit
deleted file mode 100644 (file)
index 267c746..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-# 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.
-
-# Manage indexing of Nit model for Nitdoc QuickSearch.
-module doc_indexing
-
-import doc_base
-import html_templates::html_model # FIXME maybe this phase should depend on `html_render`
-private import json::static
-private import json
-
-# Generate the index for then Nitdoc QuickSearch field.
-#
-# Create a JSON object containing links to:
-#  * modules
-#  * mclasses
-#  * mpropdefs
-# All entities are grouped by name to make the research easier.
-#
-# TODO Add a way to change the output and use it from Vim or whatever.
-class IndexingPhase
-       super DocPhase
-
-       redef fun apply do
-               for mmodule in doc.mmodules do
-                       add_result_for(mmodule.name, mmodule.full_name, mmodule.nitdoc_url)
-               end
-               for mclass in doc.mclasses do
-                       add_result_for(mclass.name, mclass.full_name, mclass.nitdoc_url)
-               end
-               for mproperty in doc.mproperties do
-                       for mpropdef in mproperty.mpropdefs do
-                               if not doc.mpropdefs.has(mpropdef) then continue
-                               var full_name = mpropdef.mclassdef.mclass.full_name
-                               var cls_url = mpropdef.mclassdef.mclass.nitdoc_url
-                               var def_url = "{cls_url}#{mpropdef.nitdoc_id}.definition"
-                               add_result_for(mproperty.name, full_name, def_url)
-                       end
-               end
-               # FIXME hack, generation should be done by the render phase
-               # create destination dir if it's necessary
-               var output_dir = ctx.output_dir
-               if not output_dir.file_exists then output_dir.mkdir
-
-               render.write_to_file("{ctx.output_dir.to_s}/quicksearch-list.js")
-       end
-
-       private var table = new QuickSearchTable
-
-       private fun add_result_for(query: String, txt: String, url: String) do
-               table[query].add new QuickSearchResult(txt, url)
-       end
-
-       # Render the index content.
-       fun render: Template do
-               var tpl = new Template
-               var buffer = new Buffer
-               tpl.add buffer
-               buffer.append "var nitdocQuickSearchRawList="
-               buffer.append table.to_json
-               buffer.append ";"
-               return tpl
-       end
-end
-
-# The result map for QuickSearch.
-private class QuickSearchTable
-       super JsonMapRead[String, QuickSearchResultList]
-       super HashMap[String, QuickSearchResultList]
-
-       redef fun provide_default_value(key) do
-               var v = new QuickSearchResultList
-               assert key isa String
-               self[key] = v
-               return v
-       end
-end
-
-# A QuickSearch result list.
-private class QuickSearchResultList
-       super JsonSequenceRead[QuickSearchResult]
-       super Array[QuickSearchResult]
-end
-
-# A QuickSearch result.
-private class QuickSearchResult
-       serialize
-
-       # The text of the link.
-       var txt: String
-
-       # The destination of the link.
-       var url: String
-end
diff --git a/src/doc/doc_phases/doc_intros_redefs.nit b/src/doc/doc_phases/doc_intros_redefs.nit
deleted file mode 100644 (file)
index 605d2e1..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-# 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.
-
-# Generates lists about intros/redefs in MEntity.
-#
-# Actually, this works only for MModules and MclassDefs.
-module doc_intros_redefs
-
-import doc_structure
-import model::model_collect
-
-# Computes intro / redef mentity list for each DefinitionArticle.
-class IntroRedefListPhase
-       super DocPhase
-
-       redef fun apply do
-               for page in doc.pages.values do
-                       if not page isa MEntityPage then continue
-                       page.root.build_intro_redef_list(self, doc, page)
-               end
-       end
-end
-
-redef class DocComposite
-
-       # Computes intro / redef lists for this page.
-       #
-       # See `IntroRedefListPhase`.
-       fun build_intro_redef_list(v: IntroRedefListPhase, doc: DocModel, page: MEntityPage) do
-               for child in children do child.build_intro_redef_list(v, doc, page)
-       end
-end
-
-redef class DefinitionArticle
-       redef fun build_intro_redef_list(v, doc, page) do
-               var mentity = self.mentity
-               if mentity isa MModule then
-                       build_mmodule_list(v, doc, mentity)
-               else if mentity isa MClassDef and mentity.mmodule == page.mentity then
-                       build_mclassdef_list(v, doc, mentity)
-               end
-               super
-       end
-
-       # TODO this should move to MEntity?
-       private fun build_mmodule_list(v: IntroRedefListPhase, doc: DocModel, mmodule: MModule) do
-               var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs")
-               section.toc_title = "Intros / Redefs"
-               var group = new PanelGroup("list.group", "List")
-               var intros = mmodule.collect_intro_mclassdefs(v.doc).to_a
-               doc.mainmodule.linearize_mclassdefs(intros)
-               group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros)
-               var redefs = mmodule.collect_redef_mclassdefs(v.doc).to_a
-               doc.mainmodule.linearize_mclassdefs(redefs)
-               group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs)
-               section.add_child group
-               add_child(section)
-       end
-
-       # TODO this should move to MEntity?
-       private fun build_mclassdef_list(v: IntroRedefListPhase, doc: DocModel, mclassdef: MClassDef) do
-               var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs")
-               section.toc_title = "Intros / Redefs"
-               var group = new PanelGroup("list.group", "List")
-               var intros = mclassdef.collect_intro_mpropdefs(v.doc).to_a
-               # FIXME avoid diff changes
-               # v.ctx.mainmodule.linearize_mpropdefs(intros)
-               group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros)
-               var redefs = mclassdef.collect_redef_mpropdefs(v.doc).to_a
-               # FIXME avoid diff changes
-               # v.ctx.mainmodule.linearize_mpropdefs(redefs)
-               group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs)
-               section.add_child group
-               add_child(section)
-       end
-end
diff --git a/src/doc/doc_phases/doc_lin.nit b/src/doc/doc_phases/doc_lin.nit
deleted file mode 100644 (file)
index 7864b27..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# 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.
-
-# Add linearization lists to DefinitionArticle found in MClass pages.
-module doc_lin
-
-import doc_structure
-
-# LinPhase populates the DocPage content with linearization data.
-class LinListPhase
-       super DocPhase
-
-       # Used to sort list by linearization order
-       private var lin_sorter = new MEntityNameSorter
-
-       redef fun apply do
-               for page in doc.pages.values do page.apply_linearization(self, doc)
-       end
-end
-
-redef class DocPage
-
-       # Populates `self` with linearization data.
-       #
-       # See `LinListPhase`.
-       fun apply_linearization(v: LinListPhase, doc: DocModel) do end
-end
-
-redef class MClassPage
-       redef fun apply_linearization(v, doc) do
-               root.apply_linearization(v, doc, self)
-       end
-end
-
-redef class DocComposite
-
-       # Populates `self` with linearization data.
-       #
-       # For now, it's only used for mpropdefs linearization in MClassPage.
-       #
-       # See `LinListPhase`.
-       private fun apply_linearization(v: LinListPhase, doc: DocModel, page: DocPage) do
-               for child in children do child.apply_linearization(v, doc, page)
-       end
-end
-
-redef class DefinitionArticle
-       redef fun apply_linearization(v, doc, page) do
-               var mentity = self.mentity
-               if not mentity isa MPropDef then return
-               # Add linearization
-               var all_defs = new HashSet[MPropDef]
-               for local_def in local_defs(page.as(MClassPage), mentity.mproperty) do
-                       all_defs.add local_def
-                       var smpropdef = local_def
-                       while not smpropdef.is_intro do
-                               smpropdef = smpropdef.lookup_next_definition(
-                                       doc.mainmodule, smpropdef.mclassdef.bound_mtype)
-                               all_defs.add smpropdef
-                       end
-               end
-               var lin = all_defs.to_a
-               doc.mainmodule.linearize_mpropdefs(lin)
-               if lin.length > 1 then
-                       add_child new DefinitionLinArticle("{mentity.nitdoc_id}.lin", "Linearization", lin)
-               end
-       end
-
-       # Filter `page.mpropdefs` for this `mpropertie`.
-       #
-       # FIXME compatability with current templates.
-       private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
-               var mpropdefs = new HashSet[MPropDef]
-               for mpropdef in page.mpropdefs do
-                       if mpropdef.mproperty == mproperty then
-                               mpropdefs.add mpropdef
-                       end
-               end
-               return mpropdefs
-       end
-end
-
-# Display a linearized list of definitions.
-class DefinitionLinArticle
-       super DocArticle
-
-       # The linearized list to display.
-       var mentities: Array[MEntity]
-
-       redef fun is_hidden do return mentities.is_empty
-       redef var is_toc_hidden = true
-end
diff --git a/src/doc/doc_phases/doc_pages.nit b/src/doc/doc_phases/doc_pages.nit
deleted file mode 100644 (file)
index 1f7148f..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# 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.
-
-# Create DocPage instances for each documentated Mentity.
-module doc_pages
-
-import doc_base
-
-# ExtractionPhase populates the DocModel with DocPage.
-class MakePagePhase
-       super DocPhase
-
-       # Instanciates documentation pages for the given DocModel.
-       redef fun apply do
-               doc.add_page new OverviewPage("overview", "Overview")
-               doc.add_page new SearchPage("search", "Index")
-               for mgroup in doc.mgroups do
-                       doc.add_page new ReadmePage(mgroup)
-                       doc.add_page new MGroupPage(mgroup)
-               end
-               for mmodule in doc.mmodules do
-                       doc.add_page new MModulePage(mmodule)
-               end
-               for mclass in doc.mclasses do
-                       doc.add_page new MClassPage(mclass)
-               end
-               for mproperty in doc.mproperties do
-                       doc.add_page new MPropertyPage(mproperty)
-               end
-       end
-end
-
-# The Nitdoc overview page.
-class OverviewPage
-       super DocPage
-end
-
-# The Nidoc full index page.
-class SearchPage
-       super DocPage
-end
-
-# A DocPage documenting a MEntity.
-class MEntityPage
-       autoinit mentity
-       super DocPage
-
-       # Type of MEntity documented by this page.
-       type MENTITY: MEntity
-
-       # MEntity documented by this page.
-       var mentity: MENTITY
-
-       redef var id is lazy do return mentity.nitdoc_id
-       redef var title is lazy do return mentity.nitdoc_name
-end
-
-# A page that displays a `MGroup` README.
-class ReadmePage
-       super MEntityPage
-
-       redef type MENTITY: MGroup
-       redef var id is lazy do return "readme_{mentity.nitdoc_id}"
-end
-
-# A documentation page about a MGroup.
-class MGroupPage
-       super MEntityPage
-
-       redef type MENTITY: MGroup
-end
-
-# A documentation page about a MModule.
-class MModulePage
-       super MEntityPage
-
-       redef type MENTITY: MModule
-end
-
-# A documentation page about a MClass.
-class MClassPage
-       super MEntityPage
-
-       redef type MENTITY: MClass
-end
-
-# A documentation page about a MProperty.
-class MPropertyPage
-       super MEntityPage
-
-       redef type MENTITY: MProperty
-end
diff --git a/src/doc/doc_phases/doc_poset.nit b/src/doc/doc_phases/doc_poset.nit
deleted file mode 100644 (file)
index 316438e..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-# 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.
-
-# Importation and inheritance POSet for pages.
-module doc_poset
-
-import doc_pages
-import model::model_collect
-
-# This phase computes importation and inheritance POSet for pages.
-class POSetPhase
-       super DocPhase
-
-       # Populates the given DocModel.
-       redef fun apply do
-               for page in doc.pages.values do
-                       if page isa MEntityPage then page.build_poset(self, doc)
-               end
-       end
-end
-
-redef class MEntityPage
-
-       # The poset associated with this page.
-       #
-       # FIXME should be defined in subclasses
-       # as the POSet can contains other types than `SELF`
-       var poset = new POSet[MENTITY]
-
-       # Build the POSet for this page.
-       private fun build_poset(v: POSetPhase, doc: DocModel) do end
-end
-
-redef class MModulePage
-
-       # Imported modules that should appear in the documentation.
-       var imports = new HashSet[MModule]
-
-       # Clients modules that should appear in the documentation.
-       var clients = new HashSet[MModule]
-
-       redef fun build_poset(v, doc) do
-               # collect importation
-               for dep in mentity.in_importation.greaters do
-                       if dep == mentity then continue
-                       if not doc.mmodules.has(dep) then continue
-                       imports.add dep
-               end
-               # FIXME avoid diff
-               #if imports.length > 10 then
-               if mentity.in_importation.greaters.length > 10 then
-                       imports.clear
-                       for dep in mentity.in_importation.direct_greaters do
-                               if dep == mentity then continue
-                               if not doc.mmodules.has(dep) then continue
-                               imports.add dep
-                       end
-               end
-               # collect clients
-               for dep in mentity.in_importation.smallers do
-                       if dep == mentity then continue
-                       if not doc.mmodules.has(dep) then continue
-                       clients.add dep
-               end
-               if clients.length > 10 then
-                       clients.clear
-                       for dep in mentity.in_importation.direct_smallers do
-                               if dep == mentity then continue
-                               if not doc.mmodules.has(dep) then continue
-                               clients.add dep
-                       end
-               end
-               # make poset
-               var mmodules = new HashSet[MModule]
-               var mgroup = mentity.mgroup
-               if mgroup != null and mgroup.default_mmodule == mentity then
-                       mmodules.add_all mgroup.mmodules
-               end
-               mmodules.add_all imports
-               if clients.length < 10 then mmodules.add_all clients
-               mmodules.add mentity
-               build_importation_poset(doc, mmodules)
-       end
-
-       # Build the POSet of importation from a list of `mmodules`.
-       private fun build_importation_poset(doc: DocModel, mmodules: Set[MModule]): POSet[MModule] do
-               for mmodule in mmodules do
-                       if not doc.mmodules.has(mmodule) then continue
-                       poset.add_node mmodule
-                       for omodule in mmodules do
-                               if not doc.mmodules.has(omodule) then continue
-                               poset.add_node mmodule
-                               if mmodule.in_importation < omodule then
-                                       poset.add_edge(mmodule, omodule)
-                               end
-                       end
-               end
-               return poset
-       end
-end
-
-redef class MClassPage
-
-       # Direct parents classes to document.
-       var parents = new HashSet[MClass]
-
-       # Transitive ancestors classes to document.
-       #
-       # Does not contain the direct ancestors.
-       # See `parents` for that.
-       var ancestors = new HashSet[MClass]
-
-       # Direct children classes to document.
-       var children = new HashSet[MClass]
-
-       # All descendants classes to document.
-       #
-       # Does not contain the direct children.
-       # See `children` for that.
-       var descendants = new HashSet[MClass]
-
-       redef fun build_poset(v, doc) do
-               poset.add_node mentity
-
-               var h = mentity.in_hierarchy(doc.mainmodule)
-               # parents
-               for mclass in h.direct_greaters do
-                       if doc.mclasses.has(mclass) then parents.add mclass
-               end
-               # ancestors
-               for mclass in h.greaters do
-                       if mclass == mentity then continue
-                       if not doc.mclasses.has(mclass) then continue
-                       if parents.has(mclass) then continue
-                       ancestors.add mclass
-               end
-               # children
-               for mclass in h.direct_smallers do
-                       if doc.mclasses.has(mclass) then children.add mclass
-               end
-               # descendants
-               for mclass in h.smallers do
-                       if mclass == mentity then continue
-                       if not doc.mclasses.has(mclass) then continue
-                       if children.has(mclass) then continue
-                       descendants.add mclass
-               end
-               # poset
-               var mclasses = new HashSet[MClass]
-               mclasses.add_all ancestors
-               mclasses.add_all parents
-               mclasses.add_all children
-               mclasses.add_all descendants
-               mclasses.add mentity
-               build_inheritance_poset(v, doc, mclasses)
-       end
-
-       private fun build_inheritance_poset(v: POSetPhase, doc: DocModel, mclasses: Set[MClass]): POSet[MClass] do
-               for mclass in mclasses do
-                       poset.add_node mclass
-                       for oclass in mclasses do
-                               if mclass == oclass then continue
-                               poset.add_node oclass
-                               if mclass.in_hierarchy(doc.mainmodule) < oclass then
-                                       poset.add_edge(mclass, oclass)
-                               end
-                       end
-               end
-               return poset
-       end
-end
diff --git a/src/doc/doc_phases/doc_readme.nit b/src/doc/doc_phases/doc_readme.nit
deleted file mode 100644 (file)
index b7d2ac8..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-# 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.
-
-# This phase parses README files.
-module doc_readme
-
-import markdown::decorators
-intrude import markdown::wikilinks
-import doc_commands
-import doc_down
-import doc_intros_redefs
-import model::model_index
-
-# Generate content of `ReadmePage`.
-#
-# This phase extracts the structure of a `ReadmePage` from the markdown content
-# of the README file.
-# It also resolves Wikilinks and commands.
-class ReadmePhase
-       super DocPhase
-
-       redef fun apply do
-               for page in doc.pages.values do page.build_content(self, doc)
-       end
-
-       # Display a warning about something wrong in the readme file.
-       fun warning(location: nullable MDLocation, page: ReadmePage, message: String) do
-               var loc = null
-               if location != null then
-                       var mdoc = page.mentity.mdoc
-                       if mdoc != null then loc = location.to_location(mdoc.location.file)
-               end
-               ctx.warning(loc, "readme-warning", message)
-       end
-end
-
-redef class DocPage
-       # Build content of `ReadmePage` based on the content of the readme file.
-       private fun build_content(v: ReadmePhase, doc: DocModel) do end
-end
-
-redef class ReadmePage
-       redef fun build_content(v, doc) do
-               var mdoc = mentity.mdoc
-               if mdoc == null then
-                       v.warning(null, self, "Empty README for group `{mentity}`")
-                       return
-               end
-               var proc = new ReadmeMdProcessor(self, v)
-               proc.decorator = new ReadmeDecorator
-               var md = mdoc.content.join("\n")
-               proc.process(md)
-       end
-end
-
-# Markdown emitter used to produce the `ReadmeArticle`.
-class ReadmeMdProcessor
-       super MarkdownProcessor
-
-       # Readme page being decorated.
-       var page: ReadmePage
-
-       # Phase used to access doc model and toolcontext.
-       var phase: ReadmePhase
-
-       init do open_article
-
-       # Push the article template on top of the buffer stack.
-       #
-       # Subsequent markdown writting will be done in the article template.
-       #
-       # See `ReadmeArticle::md`.
-       private fun push_article(article: ReadmeArticle) do
-               buffer_stack.add article.md
-       end
-
-       private var context = new Array[DocComposite]
-
-       # Creates a new ReadmeSection in `self.toc.page`.
-       #
-       # Called from `add_headline`.
-       private fun open_section(lvl: Int, title: String) do
-               var section = new ReadmeSection(title.escape_to_c, title, lvl, self)
-               var current_section = self.current_section
-               if current_section == null then
-                       page.root.add_child(section)
-               else
-                       current_section.add_child(section)
-               end
-               current_section = section
-               context.add section
-       end
-       private var current_section: nullable ReadmeSection is noinit
-
-       # Close the current section.
-       #
-       # Ensure `context.last isa ReadmeSection`.
-       private fun close_section do
-               assert context.last isa ReadmeSection
-               context.pop
-               if context.is_empty then
-                       current_section = null
-               else
-                       current_section = context.last.as(ReadmeSection)
-               end
-       end
-
-       # Add an article at current location.
-       #
-       # This closes the current article, inserts `article` then opens a new article.
-       private fun add_article(article: DocArticle) do
-               close_article
-               var current_section = self.current_section
-               if current_section == null then
-                       page.root.add_child(article)
-               else
-                       current_section.add_child(article)
-               end
-               open_article
-       end
-
-       # Creates a new ReadmeArticle in `self.toc.page`.
-       #
-       # Called from `add_headline`.
-       private fun open_article do
-               var section: DocComposite = page.root
-               if current_section != null then section = current_section.as(not null)
-               var article = new ReadmeArticle("mdarticle-{section.children.length}", null, self)
-               section.add_child(article)
-               context.add article
-               push_article article
-       end
-
-       # Close the current article.
-       #
-       # Ensure `context.last isa ReadmeArticle`.
-       fun close_article do
-               assert context.last isa ReadmeArticle
-               context.pop
-               pop_buffer
-       end
-
-       # Find mentities matching `query`.
-       fun find_mentities(query: String): Array[MEntity] do
-               # search MEntities by full_name
-               var mentity = phase.doc.mentity_by_full_name(query)
-               if mentity != null then return [mentity]
-               # search MEntities by name
-               return phase.doc.mentities_by_name(query)
-       end
-
-       # Suggest mentities based on `query`.
-       fun suggest_mentities(query: String): Array[MEntity] do
-               return phase.doc.find(query, 3)
-       end
-
-       # Display a warning message with suggestions.
-       fun warn(token: TokenWikiLink, message: String, suggest: nullable Array[MEntity]) do
-               var msg = new Buffer
-               msg.append message
-               if suggest != null and suggest.not_empty then
-                       msg.append " (suggestions: "
-                       var i = 0
-                       for s in suggest do
-                               msg.append "`{s.full_name}`"
-                               if i < suggest.length - 1 then msg.append ", "
-                               i += 1
-                       end
-                       msg.append ")"
-               end
-               phase.warning(token.location, page, msg.write_to_string)
-       end
-end
-
-# MarkdownDecorator used to decorated the Readme file with links between doc entities.
-class ReadmeDecorator
-       super MdDecorator
-
-       # Parser used to process doc commands
-       var parser = new DocCommandParser
-
-       redef type PROCESSOR: ReadmeMdProcessor
-
-       redef fun add_headline(v, block) do
-               var txt = block.block.first_line.as(not null).value
-               var lvl = block.depth
-               if not v.context.is_empty then
-                       v.close_article
-                       while v.current_section != null do
-                               if v.current_section.as(not null).depth < lvl then break
-                               v.close_section
-                       end
-               end
-               v.open_section(lvl, txt)
-               v.open_article
-       end
-
-       redef fun add_wikilink(v, token) do
-               var link = token.link.as(not null).to_s
-               var cmd = parser.parse(link)
-               if cmd == null then
-                       # search MEntities by name
-                       var res = v.find_mentities(link.to_s)
-                       # no match, print warning and display wikilink as is
-                       if res.is_empty then
-                               v.warn(token, "Link to unknown entity `{link}`", v.suggest_mentities(link.to_s))
-                               super
-                       else
-                               add_mentity_link(v, res.first, token.name, token.comment)
-                       end
-                       return
-               end
-               cmd.render(v, token)
-       end
-
-       # Renders a link to a mentity.
-       private fun add_mentity_link(v: PROCESSOR, mentity: MEntity, name, comment: nullable Text) do
-               # TODO real link
-               var link = mentity.full_name
-               if name == null then name = mentity.name
-               if comment == null then
-                       var mdoc = mentity.mdoc
-                       if mdoc != null then comment = mdoc.synopsis
-               end
-               add_link(v, link, name, comment)
-       end
-end
-
-redef class DocCommand
-
-       # Render the content of the doc command.
-       fun render(v: ReadmeMdProcessor, token: TokenWikiLink) is abstract
-end
-
-redef class CommentCommand
-       redef fun render(v, token) do
-               var string = args.first
-               var res = v.find_mentities(string)
-               if res.is_empty then
-                       v.warn(token,
-                               "Try to include documentation of unknown entity `{string}`",
-                               v.suggest_mentities(string))
-                       return
-               end
-               v.add_article new DocumentationArticle("readme", "Readme", res.first)
-       end
-end
-
-redef class ListCommand
-       redef fun render(v, token) do
-               var string = args.first
-               var res = v.find_mentities(string)
-               if res.is_empty then
-                       v.warn(token,
-                               "Try to include article of unknown entity `{string}`",
-                               v.suggest_mentities(string))
-                       return
-               end
-               if res.length > 1 then
-                       v.warn(token, "Conflicting article for `{args.first}`", res)
-               end
-               var mentity = res.first
-               if mentity isa MModule then
-                       v.add_article new MEntitiesListArticle("Classes", null, mentity.mclassdefs)
-               else if mentity isa MClass then
-                       var mprops = mentity.collect_intro_mproperties(v.phase.doc)
-                       v.add_article new MEntitiesListArticle("Methods", null, mprops.to_a)
-               else if mentity isa MClassDef then
-                       v.add_article new MEntitiesListArticle("Methods", null, mentity.mpropdefs)
-               end
-       end
-end
-
-
-# A section found in a README.
-#
-# Produced by markdown headlines like `## Section 1.1`.
-class ReadmeSection
-       super DocSection
-
-       # The depth is based on the markdown headline depth.
-       redef var depth
-
-       # Markdown processor used to process the section title.
-       var markdown_processor: MarkdownProcessor
-
-       redef var is_hidden = false
-end
-
-# An article found in a README file.
-#
-# Basically, everything found in a README that is not a headline.
-class ReadmeArticle
-       super DocArticle
-
-       # Markdown processor used to process the article content.
-       var markdown_processor: MarkdownProcessor
-
-       # Markdown content of this article extracted from the README file.
-       var md = new FlatBuffer
-
-       redef fun is_hidden do return super and md.trim.is_empty
-end
-
-# Documentation Article to introduce from the directive `doc: Something`.
-#
-# TODO merge with DefinitionArticle once the html is simplified
-class DocumentationArticle
-       super MEntityArticle
-
-       redef var is_hidden = false
-end
-
-redef class MDLocation
-       # Translate a Markdown location in Nit location.
-       private fun to_location(file: nullable SourceFile): Location do
-               return new Location(file, line_start, line_end, column_start, column_end)
-       end
-end
diff --git a/src/doc/doc_phases/doc_structure.nit b/src/doc/doc_phases/doc_structure.nit
deleted file mode 100644 (file)
index d84a739..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-# 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.
-
-# Composes the DocComposite tree of a DocPage and organizes its content.
-module doc_structure
-
-import doc_concerns
-import modelize
-
-# StructurePhase populates the DocPage content with section and article.
-#
-# This phase only applies structure.
-# The content of the structure is choosen by the rendering phases.
-class StructurePhase
-       super DocPhase
-
-       # Used to sort ConcernsTree by rank.
-       private var concerns_sorter = new MConcernRankSorter
-
-       # Used to sort ConcernsTree by name.
-       private var name_sorter = new MEntityNameSorter
-
-       # Populates the given DocModel.
-       redef fun apply do
-               for page in doc.pages.values do page.apply_structure(self, doc)
-       end
-end
-
-redef class DocPage
-
-       # Populates `self` with structure elements like DocComposite ones.
-       #
-       # See `StructurePhase`.
-       fun apply_structure(v: StructurePhase, doc: DocModel) do end
-end
-
-redef class OverviewPage
-       redef fun apply_structure(v, doc) do
-               var article = new HomeArticle("home.article", "Home")
-               root.add_child article
-               # Packages list
-               var mpackages = doc.model.mpackages.to_a
-               var sorter = new MConcernRankSorter
-               sorter.sort mpackages
-               var section = new DocSection("packages.section", "Packages")
-               for mpackage in mpackages do
-                       section.add_child new DefinitionArticle("{mpackage.nitdoc_id}.definition", null, mpackage)
-               end
-               article.add_child section
-       end
-end
-
-redef class SearchPage
-       redef fun apply_structure(v, doc) do
-               var mmodules = doc.mmodules.to_a
-               v.name_sorter.sort(mmodules)
-               var mclasses = doc.mclasses.to_a
-               v.name_sorter.sort(mclasses)
-               var mprops = doc.mproperties.to_a
-               v.name_sorter.sort(mprops)
-               root.add_child new IndexArticle("index.article", null, mmodules, mclasses, mprops)
-       end
-end
-
-redef class MGroupPage
-       redef fun apply_structure(v, doc) do
-               var section = new MEntitySection("{mentity.nitdoc_name}.section", null, mentity)
-               root.add_child section
-               if mentity.is_root then
-                       section.add_child new IntroArticle("{mentity.mpackage.nitdoc_id}.intro", null, mentity.mpackage)
-               else
-                       section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity)
-               end
-               var concerns = self.concerns
-               if concerns == null or concerns.is_empty then return
-               # FIXME avoid diff
-               mentity.mpackage.booster_rank = -1000
-               mentity.booster_rank = -1000
-               concerns.sort_with(v.concerns_sorter)
-               mentity.mpackage.booster_rank = 0
-               mentity.booster_rank = 0
-               section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
-               for mentity in concerns do
-                       var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity)
-                       if mentity isa MModule then
-                               ssection.add_child new DefinitionArticle("{mentity.nitdoc_id}.definition", null, mentity)
-                       end
-                       section.add_child ssection
-               end
-       end
-end
-
-redef class MModulePage
-       redef fun apply_structure(v, doc) do
-               var section = new MEntitySection("{mentity.nitdoc_name}.section", null, mentity)
-               root.add_child section
-               section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity)
-               var concerns = self.concerns
-               if concerns == null or concerns.is_empty then return
-               # FIXME avoid diff
-               mentity.mgroup.mpackage.booster_rank = -1000
-               mentity.mgroup.booster_rank = -1000
-               mentity.booster_rank = -1000
-               concerns.sort_with(v.concerns_sorter)
-               mentity.mgroup.mpackage.booster_rank = 0
-               mentity.mgroup.booster_rank = 0
-               mentity.booster_rank = 0
-               section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
-               # reference list
-               for mentity in concerns do
-                       var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity)
-                       if mentity isa MModule then
-                               var mclasses = mclasses_for_mmodule(mentity).to_a
-                               v.name_sorter.sort(mclasses)
-                               for mclass in mclasses do
-                                       var article = new DefinitionListArticle(
-                                               "{mclass.intro.nitdoc_id}.definition-list", null, mclass)
-                                       var mclassdefs = mclassdefs_for(mclass).to_a
-                                       if not mclassdefs.has(mclass.intro) then
-                                               article.add_child(new DefinitionArticle(
-                                                       "{mclass.intro.nitdoc_id}.definition", null, mclass.intro))
-                                       end
-                                       doc.mainmodule.linearize_mclassdefs(mclassdefs)
-                                       for mclassdef in mclassdefs do
-                                               article.add_child(new DefinitionArticle(
-                                                       "{mclassdef.nitdoc_id}.definition", null, mclassdef))
-                                       end
-                                       ssection.add_child article
-                               end
-                       end
-                       section.add_child ssection
-               end
-       end
-
-       # Filters `self.mclassses` by intro `mmodule`.
-       private fun mclasses_for_mmodule(mmodule: MModule): Set[MClass] do
-               var mclasses = new HashSet[MClass]
-               for mclass in self.mclasses do
-                       if mclass.intro_mmodule == mmodule then
-                               mclasses.add mclass
-                       end
-               end
-               return mclasses
-       end
-
-       # Filters `self.mclassdefs` by `mclass`.
-       private fun mclassdefs_for(mclass: MClass): Set[MClassDef] do
-               var mclassdefs = new HashSet[MClassDef]
-               for mclassdef in self.mclassdefs do
-                       if mclassdef.mclass == mclass then
-                               mclassdefs.add mclassdef
-                       end
-               end
-               return mclassdefs
-       end
-end
-
-redef class MClassPage
-       redef fun apply_structure(v, doc) do
-               var section = new MEntitySection("{mentity.nitdoc_name}.section", null, mentity)
-               root.add_child section
-               section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity)
-               var concerns = self.concerns
-               if concerns == null or concerns.is_empty then return
-               # FIXME diff hack
-               mentity.intro_mmodule.mgroup.mpackage.booster_rank = -1000
-               mentity.intro_mmodule.mgroup.booster_rank = -1000
-               mentity.intro_mmodule.booster_rank = -1000
-               concerns.sort_with(v.concerns_sorter)
-               mentity.intro_mmodule.mgroup.mpackage.booster_rank = 0
-               mentity.intro_mmodule.mgroup.booster_rank = 0
-               mentity.intro_mmodule.booster_rank = 0
-               var constructors = new DocSection("{mentity.nitdoc_id}.constructors", "Constructors")
-               var minit = mentity.root_init
-               if minit != null then
-                       constructors.add_child new DefinitionArticle("{minit.nitdoc_id}.definition", null, minit)
-               end
-               section.add_child constructors
-               section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
-               for mentity in concerns do
-                       var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity)
-                       if mentity isa MModule then
-                               var mprops = mproperties_for(mentity)
-                               var by_kind = new PropertiesByKind.with_elements(mprops)
-                               for group in by_kind.groups do
-                                       v.name_sorter.sort(group)
-                                       for mprop in group do
-                                               for mpropdef in mpropdefs_for(mprop, mentity) do
-                                                       if mpropdef isa MMethodDef and mpropdef.mproperty.is_init then
-                                                               if mpropdef == minit then continue
-                                                               constructors.add_child new DefinitionArticle(
-                                                                       "{mpropdef.nitdoc_id}.definition", null, mpropdef)
-                                                       else
-                                                               ssection.add_child new DefinitionArticle(
-                                                                       "{mpropdef.nitdoc_id}.definition", null, mpropdef)
-                                                       end
-                                               end
-                                       end
-                               end
-                       end
-                       section.add_child ssection
-               end
-       end
-
-       # Filters `self.mpropdefs` by `mmodule`.
-       #
-       # FIXME diff hack
-       private fun mproperties_for(mmodule: MModule): Set[MProperty] do
-               var mprops = new HashSet[MProperty]
-               for mpropdef in self.mpropdefs do
-                       if mpropdef.mclassdef.mmodule == mmodule then
-                               mprops.add mpropdef.mproperty
-                       end
-               end
-               return mprops
-       end
-
-       # Filters `self.mpropdefs` by `mproperty`.
-       #
-       # FIXME diff hack
-       private fun mpropdefs_for(mproperty: MProperty, mmodule: MModule): Set[MPropDef] do
-               var mpropdefs = new HashSet[MPropDef]
-               for mpropdef in self.mpropdefs do
-                       if mpropdef.mproperty == mproperty and
-                               mpropdef.mclassdef.mmodule == mmodule then
-                               mpropdefs.add mpropdef
-                       end
-               end
-               return mpropdefs
-       end
-end
-
-redef class MPropertyPage
-       redef fun apply_structure(v, doc) do
-               var section = new MEntitySection("{mentity.nitdoc_name}.section", null, mentity)
-               root.add_child section
-               section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity)
-               var concerns = self.concerns
-               if concerns == null or concerns.is_empty then return
-               # FIXME diff hack
-               mentity.intro.mclassdef.mmodule.mgroup.mpackage.booster_rank = -1000
-               mentity.intro.mclassdef.mmodule.mgroup.booster_rank = -1000
-               mentity.intro.mclassdef.mmodule.booster_rank = -1000
-               concerns.sort_with(v.concerns_sorter)
-               mentity.intro.mclassdef.mmodule.mgroup.mpackage.booster_rank = 0
-               mentity.intro.mclassdef.mmodule.mgroup.booster_rank = 0
-               mentity.intro.mclassdef.mmodule.booster_rank = 0
-               section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity, concerns)
-               for mentity in concerns do
-                       var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity)
-                       if mentity isa MModule then
-                               # Add mproperties
-                               var mpropdefs = mpropdefs_for(mentity).to_a
-                               v.name_sorter.sort(mpropdefs)
-                               for mpropdef in mpropdefs do
-                                       ssection.add_child new DefinitionArticle(
-                                               "{mpropdef.nitdoc_id}.definition", null, mpropdef)
-                               end
-                       end
-                       section.add_child ssection
-               end
-       end
-
-       # Filters `self.mpropdefs` by `mmodule`.
-       private fun mpropdefs_for(mmodule: MModule): Set[MPropDef] do
-               var mpropdefs = new HashSet[MPropDef]
-               for mpropdef in self.mpropdefs do
-                       if mpropdef.mclassdef.mmodule == mmodule then
-                               mpropdefs.add mpropdef
-                       end
-               end
-               return mpropdefs
-       end
-end
-
-# A group of sections that can be displayed together in a tab.
-#
-# Display the first child and hide less relevant data in other panels.
-class TabbedGroup
-       super DocSection
-end
-
-# A group of sections that can be displayed together in a tab panel.
-class PanelGroup
-       super DocSection
-end
-
-# A DocComposite element about a MEntity.
-class MEntityComposite
-       super DocComposite
-
-       redef fun title do return mentity.nitdoc_name
-
-       # MEntity documented by this page element.
-       var mentity: MEntity
-end
-
-# A Section about a Concern.
-#
-# Those sections are used to build the page summary.
-class ConcernSection
-       super MEntityComposite
-       super DocSection
-
-       redef fun is_toc_hidden do return is_hidden
-end
-
-# An article about a Mentity.
-#
-# Used to display textual content about a MEntity.
-abstract class MEntityArticle
-       super MEntityComposite
-       super DocArticle
-end
-
-# An article that displays a list of mentities.
-class MEntitiesListArticle
-       super DocArticle
-
-       # MEntities to display.
-       var mentities: Array[MEntity]
-
-       redef fun is_hidden do return mentities.is_empty
-end
-
-
-# A section about a Mentity.
-#
-# Used to regroup content about a MEntity.
-class MEntitySection
-       super MEntityComposite
-       super DocSection
-end
-
-# An introduction article about a MEntity.
-#
-# Used at the top of a documentation page to introduce the documented MEntity.
-class IntroArticle
-       super MEntityComposite
-       super DocArticle
-
-       redef var is_hidden = false
-       redef var is_toc_hidden = true
-end
-
-# An article that display a ConcernsTreee as a list.
-class ConcernsArticle
-       super MEntityArticle
-
-       # Concerns to list in this article.
-       var concerns: ConcernsTree
-
-       redef fun is_hidden do return concerns.is_empty
-end
-
-# An article that displays a list of definition belonging to a MEntity.
-class DefinitionListArticle
-       super TabbedGroup
-       super MEntityArticle
-end
-
-# An article that display the definition text of a MEntity.
-class DefinitionArticle
-       super MEntityArticle
-
-       redef var is_hidden = false
-end
-
-# The main package article.
-class HomeArticle
-       super DocArticle
-end
-
-# An article that display an index of mmodules, mclasses and mproperties.
-class IndexArticle
-       super DocArticle
-
-       # List of mmodules to display.
-       var mmodules: Array[MModule]
-
-       # List of mclasses to display.
-       var mclasses: Array[MClass]
-
-       # List of mproperties to display.
-       var mprops: Array[MProperty]
-
-       redef fun is_hidden do
-               return mmodules.is_empty and mclasses.is_empty and mprops.is_empty
-       end
-end
-
-# Concerns ranking
-
-# Sort MConcerns based on the module importation hierarchy ranking
-# see also: `MConcern::concern_rank` and `MConcern::booster_rank`
-#
-# Comparison is made with the formula:
-#
-# ~~~nitish
-# a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
-# ~~~
-#
-# If both `a` and `b` have the same ranking,
-# ordering is based on lexicographic comparison of `a.name` and `b.name`
-class MConcernRankSorter
-       super Comparator
-       redef type COMPARED: MConcern
-
-       redef fun compare(a, b) do
-               if a.concern_rank == b.concern_rank then
-                       return a.name <=> b.name
-               end
-               return a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_rank
-       end
-end
-
-redef class MConcern
-
-       # Boost a MConcern rank
-       # see: `MConcernRankSorter`
-       # Use a positive booster to push down a result in the list
-       # A negative booster can be used to push up the result
-       var booster_rank: Int = 0 is writable
-
-       # Concern ranking used for ordering
-       # see: `MConcernRankSorter`
-       # Rank can be positive or negative
-       fun concern_rank: Int is abstract
-end
-
-redef class MPackage
-       redef var concern_rank is lazy do
-               var max = 0
-               for mgroup in mgroups do
-                       var mmax = mgroup.concern_rank
-                       if mmax > max then max = mmax
-               end
-               return max + 1
-       end
-end
-
-redef class MGroup
-       redef var concern_rank is lazy do
-               var max = 0
-               for mmodule in mmodules do
-                       var mmax = mmodule.concern_rank
-                       if mmax > max then max = mmax
-               end
-               return max + 1
-       end
-end
-
-redef class MModule
-       redef var concern_rank is lazy do
-               var max = 0
-               for p in in_importation.direct_greaters do
-                       var pmax = p.concern_rank
-                       if pmax > max then max = pmax
-               end
-               return max + 1
-       end
-end
diff --git a/src/doc/doc_phases/doc_test.nit b/src/doc/doc_phases/doc_test.nit
deleted file mode 100644 (file)
index 4d68d2a..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# 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.
-
-# Print the generated DocModel in stdout.
-#
-# Mainly used for tests.
-module doc_test
-
-import doc_structure
-import counter
-
-redef class ToolContext
-
-       # File pattern used to link documentation to source code.
-       var opt_test = new OptionBool("Print test data (metrics and structure)", "--test")
-
-       redef init do
-               super
-               option_context.add_option(opt_test)
-       end
-end
-
-# Display the DocModel in stdout.
-class DocTestPhase
-       super DocPhase
-
-       redef fun apply do
-               if not ctx.opt_test.value then return
-               # Pages metrics
-               var page_counter = new Counter[String]
-               var pages = doc.pages.keys.to_a
-               default_comparator.sort(pages)
-               for title in pages do
-                       var page = doc.pages[title]
-                       page_counter.inc page.class_name
-                       print page.pretty_print.write_to_string
-               end
-               print "Generated {doc.pages.length} pages"
-               page_counter.print_elements(100)
-               # Model metrics
-               var model_counter = new Counter[String]
-               for mentity in doc.mentities do
-                       model_counter.inc mentity.class_name
-               end
-               print "Found {doc.mentities.length} mentities"
-               model_counter.print_elements(100)
-       end
-end
diff --git a/src/doc/html_templates/html_components.nit b/src/doc/html_templates/html_components.nit
deleted file mode 100644 (file)
index fa3bd69..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-# 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.
-
-# HTML templates used by Nitdoc to generate API documentation
-# Pages are assembled using `Template`
-module html_components
-
-import doc_base
-import html::bootstrap
-import json
-
-# A label with a text content.
-class DocHTMLLabel
-       super BSLabel
-
-       redef init do
-               css_classes.clear
-               css_classes.add "label"
-       end
-
-       # Init this label from css classes.
-       init with_classes(classes: Array[String]) do
-               init("label", "")
-               css_classes.add_all classes
-       end
-end
-
-# A component that display tabbed data.
-class DocTabs
-       super BSComponent
-       autoinit(html_id, drop_text, css_classes)
-
-       # HTML id of this component.
-       var html_id: String
-
-       # Text displayed on the tabs dropdown button.
-       var drop_text: String
-
-       # Panels to display in this tab group.
-       var panels = new Array[DocTabPanel]
-
-       # Droplist containing links to panels.
-       #
-       # Can also be used to add external links.
-       var drop_list: DocTabsDrop is lazy do return new DocTabsDrop(html_id, drop_text)
-
-       # Adds a new `panel` to that tab.
-       #
-       # You should always use this instead of `panels.add` because it also set the
-       # `drop_list` entry.
-       fun add_panel(panel: DocTabPanel) do
-               drop_list.add_li panel.render_tab
-               panels.add panel
-       end
-
-       redef fun rendering do
-               if panels.is_empty then return
-               panels.first.is_active = true
-               add "<div role=\"tabpanel\">"
-               if drop_list.items.length > 1 then add drop_list
-               add " <div class=\"tab-content\">"
-               for panel in panels do
-                       add panel
-               end
-               add " </div>"
-               add "</div>"
-       end
-end
-
-# A list of tab regrouped in a dropdown
-class DocTabsDrop
-       super UnorderedList
-       autoinit(html_id, html_title, items, css_classes)
-
-       # HTML id used by the tabs group.
-       var html_id: String
-
-       # Title to display in the tab item.
-       var html_title: String
-
-       redef fun rendering do
-               add """<ul id="{{{html_id}}}-tabs" class="nav pull-right" role="tablist">"""
-               add """ <li role="presentation" class="dropdown pull-right">"""
-               add """  <a href="#" id="{{{html_id}}}-drop" class="dropdown-toggle"
-                         data-toggle="dropdown" aria-controls="{{{html_id}}}-contents"
-                         aria-expanded="false">"""
-        add html_title
-               add """ <span class="glyphicon glyphicon-menu-hamburger"></span>"""
-               add """ </a>"""
-               add """ <ul class="dropdown-menu" role="menu"
-                        aria-labelledby="{{{html_id}}}-drop" id="{{{html_id}}}-contents">"""
-               for item in items do add item
-               add "  </ul>"
-        add " </li>"
-        add "</ul>"
-       end
-end
-
-# A panel that goes in a DocTabs.
-class DocTabPanel
-       super BSComponent
-       autoinit(html_id, tab_title, html_content, is_active, css_classes)
-
-       # HTML id of this panel.
-       var html_id: String
-
-       # Title of this panel as displayed in the tab label.
-       var tab_title: String
-
-       # HTML content of this panel.
-       var html_content: Writable is writable
-
-       # Is this panel visible by default?
-       var is_active = false is optional
-
-       redef fun rendering do
-               var active = ""
-               if is_active then active = "active in"
-               add "<div role=\"tabpanel\" class=\"tab-pane fade {active}\""
-               add "  id=\"{html_id}\" aria-labelledby=\"{html_id}-tab\">"
-               add html_content
-               add "</div>"
-       end
-
-       private fun render_tab: DocTabItem do return new DocTabItem(tab_title, html_id)
-end
-
-# A ListItem that goes in a DocTabsDrop.
-private class DocTabItem
-       super ListItem
-       autoinit(text, target_id, css_classes)
-
-       # Panel id to trigger when the link is clicked.
-       var target_id: String
-
-       redef fun rendering do
-               add "<li{render_css_classes}>"
-               add " <a role=\"tab\" data-toggle=\"tab\" aria-expanded=\"false\" tabindex=\"-1\""
-               add "   id=\"{target_id}-tab\" href=\"#{target_id}\" aria-controls=\"{target_id}\">"
-               add text
-               add " </a>"
-               add "</li>"
-       end
-end
-
-# A HTML tag attribute
-#  `<tag attr="value">`
-#
-# ~~~nit
-# var attr: TagAttribute
-#
-# attr = new TagAttribute("foo", null)
-# assert attr.write_to_string == " foo=\"\""
-#
-# attr = new TagAttribute("foo", "bar<>")
-# assert attr.write_to_string == " foo=\"bar&lt;&gt;\""
-# ~~~
-class TagAttribute
-       super Template
-
-       var name: String
-       var value: nullable String
-
-       redef fun rendering do
-               var value = self.value
-               if value == null then
-                       # SEE: http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes
-                       add " {name.html_escape}=\"\""
-               else
-                       add " {name.html_escape}=\"{value.html_escape}\""
-               end
-       end
-end
-
-# Javacript template that can be added into a DocPage.
-class TplScript
-       super Template
-
-       # HTML attributes to add in this tag.
-       var attrs = new Array[TagAttribute]
-
-       # Text content of this script tag.
-       var content: nullable Writable = null is writable
-
-       init do
-               attrs.add(new TagAttribute("type", "text/javascript"))
-       end
-
-       # Render the content of this script.
-       protected fun render_content do
-               if content != null then add content.as(not null)
-       end
-
-       redef fun rendering do
-               add "<script"
-               for attr in attrs do add attr
-               addn ">"
-               render_content
-               addn "</script>"
-       end
-end
-
-# JS script for Piwik Tracker
-class TplPiwikScript
-       super TplScript
-
-       # Piwik URL to use for this tracker.
-       var tracker_url: String
-
-       # Site ID used on Piwik system.
-       var site_id: String
-
-       redef fun render_content do
-               var site_id = self.site_id.to_json
-               var tracker_url = self.tracker_url.trim
-               if tracker_url.chars.last != '/' then tracker_url += "/"
-               tracker_url = "://{tracker_url}".to_json
-
-               addn "<!-- Piwik -->"
-               addn "var _paq = _paq || [];"
-               addn " _paq.push([\"trackPageView\"]);"
-               addn " _paq.push([\"enableLinkTracking\"]);"
-               addn "(function() \{"
-               addn " var u=((\"https:\" == document.location.protocol) ? \"https\" : \"http\") + {tracker_url};"
-               addn " _paq.push([\"setTrackerUrl\", u+\"piwik.php\"]);"
-               addn " _paq.push([\"setSiteId\", {site_id}]);"
-               addn " var d=document, g=d.createElement(\"script\"), s=d.getElementsByTagName(\"script\")[0]; g.type=\"text/javascript\";"
-               addn " g.defer=true; g.async=true; g.src=u+\"piwik.js\"; s.parentNode.insertBefore(g,s);"
-               addn "\})();"
-       end
-end
diff --git a/src/doc/html_templates/html_model.nit b/src/doc/html_templates/html_model.nit
deleted file mode 100644 (file)
index 820a9a3..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-# 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.
-
-# HTML templates for Nit model MEntities.
-module html_model
-
-import doc_base
-import html_components
-import ordered_tree
-import model_html
-
-redef class MEntity
-       # URL of this entity’s Nitdoc page.
-       fun nitdoc_url: String is abstract
-
-       # Returns a Link to the mentity `html_url`.
-       #
-       # Example: `<a href="html_url" title="mdoc.short_comment">html_short_name</a>
-       redef var html_link is lazy do
-               var tpl = new Link(nitdoc_url, html_name)
-               var mdoc = mdoc_or_fallback
-               if mdoc != null then
-                       tpl.title = mdoc.synopsis
-               end
-               return tpl
-       end
-
-       # Returns a Link to the mentity `nitdoc_id`.
-       #
-       # Example: `<a href="#nitdoc_id" title="mdoc.short_comment">html_short_name</a>
-       fun html_link_to_anchor: Link do
-               var tpl = new Link("#{nitdoc_id}", html_name)
-               var mdoc = mdoc_or_fallback
-               if mdoc != null then
-                       tpl.title = mdoc.synopsis
-               end
-               return tpl
-       end
-
-       # A li element that can go in a `HTMLList`.
-       fun html_list_item: ListItem do
-               var tpl = new Template
-               tpl.add new DocHTMLLabel.with_classes(css_classes)
-               tpl.add html_link
-               var comment = html_synopsis
-               if comment != null then
-                       tpl.add ": "
-                       tpl.add comment
-               end
-               return new ListItem(tpl)
-       end
-end
-
-redef class MPackage
-       redef var nitdoc_id = name.to_cmangle is lazy
-
-       redef fun nitdoc_url do
-               var root = self.root
-               if root == null then return super
-               return root.nitdoc_url
-       end
-end
-
-redef class MGroup
-       redef var nitdoc_id is lazy do
-               var parent = self.parent
-               if parent != null then
-                       return "{parent.nitdoc_id}__{name.to_cmangle}"
-               end
-               return name.to_cmangle
-       end
-
-       redef fun nitdoc_url do return "group_{nitdoc_id}.html"
-end
-
-redef class MModule
-       redef var nitdoc_id is lazy do
-               var mgroup = self.mgroup
-               if mgroup != null then
-                       if mgroup.mmodules.length == 1 then
-                               return "{mgroup.nitdoc_id}-"
-                       else
-                               return "{mgroup.nitdoc_id}__{name.to_cmangle}"
-                       end
-               end
-               return name.to_cmangle
-       end
-
-       redef fun nitdoc_url do return "module_{nitdoc_id}.html"
-end
-
-redef class MClass
-       redef var nitdoc_id = "{intro_mmodule.nitdoc_id}__{name.to_cmangle}" is lazy
-       redef fun nitdoc_url do return "class_{nitdoc_id}.html"
-end
-
-redef class MClassDef
-       redef var nitdoc_id = "{mmodule.nitdoc_id}__{name.to_cmangle}" is lazy
-       redef fun nitdoc_url do return "{mclass.nitdoc_url}#{nitdoc_id}"
-end
-
-redef class MProperty
-       redef var nitdoc_id = "{intro_mclassdef.mclass.nitdoc_id}__{name.to_cmangle}" is lazy
-       redef fun nitdoc_url do return "property_{nitdoc_id}.html"
-end
-
-redef class MPropDef
-       redef var nitdoc_id = "{mclassdef.nitdoc_id}__{name.to_cmangle}" is lazy
-       redef fun nitdoc_url do return "{mproperty.nitdoc_url}#{nitdoc_id}"
-end
-
-redef class MAttributeDef
-
-       redef fun html_modifiers do
-               var res = super
-               res.add "var"
-               return res
-       end
-
-       redef fun html_short_signature do return new Template
-
-       redef fun html_signature do
-               var static_mtype = self.static_mtype
-               var tpl = new Template
-               if static_mtype != null then
-                       tpl.add ": "
-                       tpl.add static_mtype.html_signature
-               end
-               return tpl
-       end
-end
-
-redef class MParameterType
-       redef fun html_link do
-               return new Link("{mclass.nitdoc_url}#FT_{name.to_cmangle}", name, "formal type")
-       end
-end
-
-redef class MVirtualType
-       redef fun html_link do return mproperty.intro.html_link
-end
-
-redef class ConcernsTree
-       # Render `self` as a hierarchical UnorderedList.
-       fun html_list: UnorderedList do
-               var lst = new UnorderedList
-               lst.css_classes.add "list-unstyled list-definition"
-               for r in roots do
-                       var li = r.html_concern_item
-                       lst.add_li li
-                       build_html_list(r, li)
-               end
-               return lst
-       end
-
-       # Build the html list recursively.
-       private fun build_html_list(e: MConcern, li: ListItem) do
-               if not sub.has_key(e) then return
-               var subs = sub[e]
-               var lst = new UnorderedList
-               lst.css_classes.add "list-unstyled list-definition"
-               for e2 in subs do
-                       if e2 isa MGroup and e2.is_root then
-                               build_html_list(e2, li)
-                       else
-                               var sli = e2.html_concern_item
-                               lst.add_li sli
-                               build_html_list(e2, sli)
-                       end
-               end
-               var text = new Template
-               text.add li.text
-               if not lst.is_empty then text.add lst
-               li.text = text
-       end
-end
-
-redef class MConcern
-       # Return a li element for `self` that can be displayed in a concern list
-       private fun html_concern_item: ListItem do
-               var lnk = html_link
-               var tpl = new Template
-               tpl.add new Link("#{nitdoc_id}.concern", lnk.text, lnk.title)
-               var comment = html_synopsis
-               if comment != null then
-                       tpl.add ": "
-                       tpl.add comment
-               end
-               return new ListItem(tpl)
-       end
-end
-
-################################################################################
-# Additions to `model_ext`.
-
-redef class MRawType
-       redef fun html_signature do
-               var tpl = new Template
-
-               for part in parts do
-                       if part.target != null then
-                               tpl.add part.target.as(not null).html_link
-                       else
-                               tpl.add part.text.html_escape
-                       end
-               end
-               return tpl
-       end
-end
-
-redef class MInnerClass
-       redef fun nitdoc_url do return inner.nitdoc_url
-       redef fun html_signature do return inner.html_signature
-end
-
-redef class MInnerClassDef
-       redef fun nitdoc_url do return inner.nitdoc_url
-
-       redef fun html_link_to_anchor do return inner.html_link_to_anchor
-       redef fun html_link do return inner.html_link
-       redef fun html_signature do return inner.html_signature
-end
diff --git a/src/doc/html_templates/html_templates.nit b/src/doc/html_templates/html_templates.nit
deleted file mode 100644 (file)
index 9f8390e..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-# 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.
-
-# Introduces templates that compose the documentation HTML rendering.
-module html_templates
-
-import html_model
-import html::bootstrap
-import doc_phases::doc_structure
-import doc_phases::doc_hierarchies
-import doc_phases::doc_graphs
-import doc_phases::doc_intros_redefs
-import doc_phases::doc_lin
-import doc_phases::doc_readme
-intrude import doc_down
-
-# Renders the page as HTML.
-redef class DocPage
-       super Template
-
-       # Page url.
-       var html_url: String is writable, noinit
-
-       # Directory where css, js and other assets can be found.
-       var shareurl: String is writable, noinit
-
-       # Attributes of the body tag element.
-       var body_attrs = new Array[TagAttribute]
-
-       # Top menu template if any.
-       var topmenu: DocTopMenu is writable, noinit
-
-       # Sidebar template if any.
-       var sidebar: nullable DocSideBar = null is writable
-
-       # Footer content if any.
-       var footer: nullable Writable = null is writable
-
-       # JS scripts to append at the end of the body
-       var scripts = new Array[TplScript]
-
-       # Renders the html `<head>`.
-       private fun render_head do
-               var css = (self.shareurl / "css").html_escape
-               var vendors = (self.shareurl / "vendors").html_escape
-
-               addn "<!DOCTYPE html>"
-               addn "<head>"
-               addn " <meta charset='utf-8'/>"
-               addn " <!--link rel='stylesheet' href='{css}/Nitdoc.UI.css' type='text/css'/-->"
-               addn " <link rel='stylesheet' href='{vendors}/bootstrap/css/bootstrap.min.css'/>"
-               addn " <link rel='stylesheet' href='{css}/nitdoc.bootstrap.css'/>"
-               addn " <link rel='stylesheet' href='{css}/nitdoc.css'/>"
-               addn " <link rel='stylesheet' href='{css}/Nitdoc.QuickSearch.css'/>"
-               addn " <link rel='stylesheet' href='{css}/Nitdoc.ModalBox.css'/>"
-               addn " <link rel='stylesheet' href='{css}/Nitdoc.GitHub.css'/>"
-               addn " <title>{title.html_escape}</title>"
-               addn "</head>"
-               add "<body"
-               for attr in body_attrs do add attr
-               addn ">"
-       end
-
-       # Renders the footer and content.
-       private fun render_content do
-               add root
-               if footer != null then
-                       addn "<div class='well footer'>"
-                       add footer.as(not null)
-                       addn "</div>"
-               end
-       end
-
-       # Render JS scripts
-       private fun render_footer do
-               var vendors = (self.shareurl / "vendors").html_escape
-               var js = (self.shareurl / "js").html_escape
-
-               addn "<script src='{vendors}/jquery/jquery-1.11.1.min.js'></script>"
-               addn "<script src='{vendors}/jquery/jquery-ui-1.10.4.custom.min.js'></script>"
-               addn "<script src='{vendors}/bootstrap/js/bootstrap.min.js'></script>"
-               addn "<script src='{js}/lib/utils.js'></script>"
-               addn "<script src='{js}/plugins/filtering.js'></script>"
-               addn "<script src='quicksearch-list.js'></script>"
-               addn "<script src='{js}/plugins/quicksearch.js'></script>"
-               for script in scripts do add script
-               addn """<script>
-                       $(function () {
-                               $("[data-toggle='tooltip']").tooltip();
-                               $("[data-toggle='popover']").popover();
-                       });
-               </script>"""
-               addn "</body>"
-               addn "</html>"
-       end
-
-       # Render the whole page
-       redef fun rendering do
-               render_head
-               addn "<div class='container-fluid'>"
-               addn " <div class='row'>"
-               add topmenu
-               addn " </div>"
-               addn " <div class='row' id='content'>"
-               var sidebar = self.sidebar
-               if sidebar != null then
-                       addn "<div class='col col-xs-3 col-lg-2'>"
-                       add sidebar
-                       addn "</div>"
-                       addn "<div class='col col-xs-9 col-lg-10' data-spy='scroll' data-target='.summary'>"
-                       render_content
-                       addn "</div>"
-               else
-                       addn "<div class='col col-xs-12'>"
-                       render_content
-                       addn "</div>"
-               end
-               addn " </div>"
-               addn "</div>"
-               render_footer
-       end
-
-       # Render table of content for this page.
-       fun html_toc: UnorderedList do
-               var lst = new UnorderedList
-               lst.css_classes.add "nav"
-               for child in root.children do
-                       child.render_toc_item(lst)
-               end
-               return lst
-       end
-end
-
-# Top menu bar template.
-#
-# FIXME should be a Bootstrap component template
-# At this moment, the topmenu structure stills to specific to Nitdoc to use the
-# generic component.
-class DocTopMenu
-       super UnorderedList
-
-       # Brand link to display in first position of the top menu.
-       #
-       # This is where you want to put your logo.
-       var brand: nullable Writable is noinit, writable
-
-       # Active menu item.
-       #
-       # Depends on the current page, this allows to hilighted the current item.
-       #
-       # FIXME should be using Boostrap breadcrumbs component.
-       # This will still like this to avoid diff and be changed in further fixes
-       # when we will modify the output.
-       var active_item: nullable ListItem is noinit, writable
-
-       redef fun rendering do
-               addn "<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
-               addn " <div class='container-fluid'>"
-               addn "  <div class='navbar-header'>"
-               add "   <button type='button' class='navbar-toggle' "
-               addn "       data-toggle='collapse' data-target='#topmenu-collapse'>"
-               addn "    <span class='sr-only'>Toggle menu</span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "   </button>"
-               if brand != null then
-                       add "<span class='navbar-brand'>"
-                       add brand.write_to_string
-                       add "</span>"
-               end
-               addn "  </div>"
-               addn "  <div class='collapse navbar-collapse' id='topmenu-collapse'>"
-               addn "   <ul class='nav navbar-nav'>"
-               for item in items do
-                       if item == active_item then item.css_classes.add "active"
-                       add item.write_to_string
-               end
-               addn "   </ul>"
-               addn "  </div>"
-               addn " </div>"
-               addn "</nav>"
-       end
-end
-
-# Nitdoc sidebar template.
-class DocSideBar
-       super Template
-
-       # Sidebar contains `DocSideBox`.
-       var boxes = new Array[DocSideBox]
-
-       redef fun rendering do
-               if boxes.is_empty then return
-               addn "<div id='sidebar'>"
-               for box in boxes do add box
-               addn "</div>"
-       end
-end
-
-# Something that can be put in a DocSideBar.
-class DocSideBox
-       super Template
-
-       # Box HTML id, used for Bootstrap collapsing feature.
-       #
-       # Use `html_title.to_cmangle` by default.
-       var id: String is lazy do return title.write_to_string.to_cmangle
-
-       # Title of the box to display.
-       var title: Writable
-
-       # Content to display in the box.
-       var content: Writable
-
-       # Is the box opened by default?
-       #
-       # Otherwise, the user will have to clic on the title to display the content.
-       #
-       # Default is `true`.
-       var is_open = true is writable
-
-       redef fun rendering do
-               var open = ""
-               if is_open then open = "in"
-               addn "<div class='panel'>"
-               addn " <div class='panel-heading'>"
-               add "  <a data-toggle='collapse' data-parent='#sidebar'"
-               add "   data-target='#box_{id}' href='#'>"
-               add title
-               addn "  </a>"
-               addn " </div>"
-               addn " <div id='box_{id}' class='summary panel-body collapse {open}'>"
-               add content
-               addn " </div>"
-               addn "</div>"
-       end
-end
-
-redef class DocComposite
-       super Template
-
-       # HTML anchor id
-       var html_id: String is writable, lazy do return id
-
-       # Title to display if any.
-       #
-       # This title can be decorated with HTML.
-       var html_title: nullable Writable is writable, lazy do return title
-
-       # Subtitle to display if any.
-       var html_subtitle: nullable Writable is noinit, writable
-
-       # Render the element title and subtitle.
-       private fun render_title do
-               if html_title != null then
-               var header = new Header(hlvl, html_title.write_to_string)
-               header.css_classes.add "signature"
-               addn header
-               end
-               if html_subtitle != null then
-                       addn "<div class='info subtitle'>"
-                       addn html_subtitle.write_to_string
-                       addn "</div>"
-               end
-       end
-
-       # Render the element body.
-       private fun render_body do
-               for child in children do addn child.write_to_string
-       end
-
-       redef fun rendering do
-               if is_hidden then return
-               render_title
-               render_body
-       end
-
-       # Level <hX> for HTML heading.
-       private fun hlvl: Int do return depth
-
-       # A short, undecorated title that goes in the table of contents.
-       #
-       # By default, returns `html_title.to_s`, subclasses should redefine it.
-       var html_toc_title: nullable String is lazy, writable do
-               if html_title == null then return toc_title
-               return html_title.write_to_string
-       end
-
-       # Render this element in a table of contents.
-       private fun render_toc_item(lst: UnorderedList) do
-               if is_toc_hidden or html_toc_title == null then return
-
-               var content = new Template
-               content.add new Link("#{html_id}", html_toc_title.to_s)
-               if not children.is_empty then
-                       var sublst = new UnorderedList
-                       sublst.css_classes.add "nav"
-                       for child in children do
-                               child.render_toc_item(sublst)
-                       end
-                       content.add sublst
-               end
-               lst.add_li new ListItem(content)
-       end
-
-       # ID used in HTML tab labels.
-       #
-       # We sanitize it for Boostrap JS panels that do not like ":" and "." in ids.
-       var html_tab_id: String is lazy do
-               var id = html_id.replace(":", "")
-               id = id.replace(".", "")
-               return "{id}-tab"
-       end
-end
-
-redef class DocRoot
-       redef fun rendering do
-               for child in children do addn child.write_to_string
-       end
-end
-
-redef class DocSection
-       super BSComponent
-
-       redef fun css_classes do return new Array[String]
-
-       redef fun rendering do
-               if is_hidden then
-                       addn "<a id=\"{html_id}\"></a>"
-                       return
-               end
-               addn "<section{render_css_classes} id=\"{html_id}\">"
-               render_title
-               render_body
-               addn "</section>"
-       end
-end
-
-redef class DocArticle
-       super BSComponent
-
-       redef fun css_classes do return new Array[String]
-
-       redef fun rendering do
-               if is_hidden then return
-               addn "<article{render_css_classes} id=\"{html_id}\">"
-               render_title
-               render_body
-               addn "</article>"
-       end
-end
-
-redef class TabbedGroup
-       redef fun render_body do
-               var tabs = new DocTabs("{html_id}.tabs", "")
-               for child in children do
-                       if child.is_hidden then continue
-                       var title = child.html_toc_title or else child.toc_title or else ""
-                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
-               end
-               addn tabs
-       end
-end
-
-redef class PanelGroup
-       redef var html_title = null
-       redef var toc_title is lazy do return title or else ""
-       redef var is_toc_hidden = true
-end
-
-redef class HomeArticle
-       redef var html_title = "Overview"
-
-       # HTML content to display on the home page.
-       #
-       # This attribute is set by the `doc_render` phase who knows the context.
-       var content: nullable String is noinit, writable
-
-       redef fun render_body do
-               var content = self.content
-               if content != null then add content
-               super
-       end
-end
-
-redef class IndexArticle
-       redef var html_title = "Index"
-
-       redef fun render_body do
-               addn "<div class='container-fluid'>"
-               addn " <div class='row'>"
-               render_list("Modules", mmodules)
-               render_list("Classes", mclasses)
-               render_list("Properties", mprops)
-               addn "</div>"
-               addn "</div>"
-       end
-
-       # Displays a list from the content of `mentities`.
-       private fun render_list(title: String, mentities: Array[MEntity]) do
-               if mentities.is_empty then return
-               addn "<div class='col-xs-4'>"
-               addn new Header(3, title)
-               var lst = new UnorderedList
-               for mentity in mentities do
-                       if mentity isa MProperty then
-                               var tpl = new Template
-                               tpl.add mentity.intro.html_link
-                               tpl.add " ("
-                               tpl.add mentity.intro.mclassdef.mclass.html_link
-                               tpl.add ")"
-                               lst.add_li new ListItem(tpl)
-                       else
-                               lst.add_li new ListItem(mentity.html_link)
-                       end
-               end
-               addn lst
-               addn "</div>"
-       end
-end
-
-redef class MEntityComposite
-       redef var html_title is lazy do return mentity.nitdoc_name
-end
-
-redef class MEntitySection
-       redef var html_title is lazy do return mentity.html_name
-       redef var html_subtitle is lazy do return mentity.html_declaration
-end
-
-redef class ConcernSection
-       redef var html_title is lazy do return "in {mentity.nitdoc_name}"
-end
-
-redef class IntroArticle
-       redef var html_title = null
-
-       # Link to source to display if any.
-       var html_source_link: nullable Writable is noinit, writable
-
-       redef fun render_body do
-               var tabs = new DocTabs("{html_id}.tabs", "")
-               var comment = mentity.html_documentation
-               if mentity isa MPackage then
-                       comment = mentity.html_synopsis
-               end
-               if comment != null then
-                       tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
-               end
-               for child in children do
-                       if child.is_hidden then continue
-                       var title = child.html_toc_title or else child.toc_title or else ""
-                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
-               end
-               var lnk = html_source_link
-               if lnk != null then
-                       tabs.drop_list.items.add new ListItem(lnk)
-               end
-               addn tabs
-       end
-end
-
-redef class ConcernsArticle
-       redef var html_title = "Concerns"
-       redef fun render_body do add concerns.html_list
-end
-
-redef class DefinitionListArticle
-       redef var html_title is lazy do
-               var title = new Template
-               title.add mentity.html_icon
-               title.add mentity.html_link
-               return title
-       end
-
-       redef var html_subtitle is lazy do return mentity.html_namespace
-       redef var html_toc_title is lazy do return mentity.html_name
-end
-
-redef class DefinitionArticle
-       redef var html_title is lazy do return mentity.html_name
-       redef var html_subtitle is lazy do return mentity.html_declaration
-
-       # Does `self` display only it's title and no body?
-       #
-       # FIXME diff hack
-       var is_no_body: Bool = false is writable
-
-       # Does `self` display only the short content as definition?
-       #
-       # FIXME diff hack
-       var is_short_comment: Bool = false is writable
-
-       # Link to source to display if any.
-       var html_source_link: nullable Writable is noinit, writable
-
-       redef fun render_body do
-               var tabs = new DocTabs("{html_id}.tabs", "")
-               if not is_no_body then
-                       var comment
-                       if is_short_comment or mentity isa MPackage then
-                               comment = mentity.html_synopsis
-                       else
-                               comment = mentity.html_documentation
-                       end
-                       if comment != null then
-                               tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
-                       end
-               end
-               for child in children do
-                       if child.is_hidden then continue
-                       var title = child.html_toc_title or else child.toc_title or else ""
-                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
-               end
-               var lnk = html_source_link
-               if lnk != null then
-                       tabs.drop_list.items.add new ListItem(lnk)
-               end
-               addn tabs
-       end
-end
-
-redef class MEntitiesListArticle
-       redef fun render_body do
-               var lst = new UnorderedList
-               lst.css_classes.add "list-unstyled list-definition"
-               for mentity in mentities do
-                       lst.add_li mentity.html_list_item
-               end
-               add lst
-       end
-end
-
-redef class DefinitionLinArticle
-       redef fun render_body do
-               var lst = new UnorderedList
-               lst.css_classes.add "list-unstyled list-labeled"
-               for mentity in mentities do
-                       if not mentity isa MPropDef then continue # TODO handle all mentities
-                       var tpl = new Template
-                       tpl.add mentity.mclassdef.html_namespace
-                       var comment = mentity.mclassdef.html_synopsis
-                       if comment != null then
-                               tpl.add ": "
-                               tpl.add comment
-                       end
-                       var li = new ListItem(tpl)
-                       li.css_classes.add "signature"
-                       lst.add_li li
-               end
-               add lst
-       end
-end
-
-redef class GraphArticle
-       redef var html_title = null
-
-       # Graph in SVG with clickable map.
-       #
-       # This attribute is set by the `doc_render` phase who knows the context.
-       var svg: nullable String = null is writable
-
-       redef fun render_body do
-               addn "<div class=\"text-center\">"
-               var svg = self.svg
-               if svg != null then add svg
-               addn "</div>"
-       end
-end
-
-redef class ReadmeSection
-       redef var html_id is lazy do
-               return markdown_processor.decorator.strip_id(html_title.as(not null).to_s)
-       end
-
-       redef var html_title is lazy do
-               return markdown_processor.process(title.as(not null))
-       end
-end
-
-redef class ReadmeArticle
-       redef var html_id = ""
-       redef var html_title = null
-       redef var is_toc_hidden = true
-
-       redef fun render_body do
-               add markdown_processor.process(md.trim.write_to_string)
-       end
-end
-
-redef class DocumentationArticle
-       redef var html_title is lazy do
-               var synopsis = mentity.html_synopsis
-               if synopsis == null then return mentity.html_link
-               return "{mentity.html_link.write_to_string} &ndash; {synopsis.write_to_string}"
-       end
-
-       redef var html_subtitle is lazy do return null
-       redef var html_toc_title is lazy do return mentity.html_name
-       redef var is_toc_hidden is lazy do return depth > 3
-
-       redef fun render_body do
-               var tabs = new DocTabs("{html_id}.tabs", "")
-               var comment = mentity.html_comment
-               if comment != null then
-                       tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
-               end
-               for child in children do
-                       if child.is_hidden then continue
-                       var title = child.html_toc_title or else child.toc_title or else ""
-                       tabs.add_panel new DocTabPanel(child.html_tab_id, title, child)
-               end
-               addn tabs
-       end
-end
diff --git a/src/doc/html_templates/model_html.nit b/src/doc/html_templates/model_html.nit
deleted file mode 100644 (file)
index 8e89dd4..0000000
+++ /dev/null
@@ -1,676 +0,0 @@
-# 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.
-
-# Translate mentities to html blocks.
-module model_html
-
-import model
-import doc::doc_down
-import html::bootstrap
-
-redef class MEntity
-
-       # Returns the MEntity name escaped for html.
-       #
-       # * MPackage: `foo`
-       # * MGroup: `foo`
-       # * MModule: `foo`
-       # * MClass: `Foo[E]`
-       # * MClassDef: `Foo[E]`
-       # * MProperty: `foo(e)`
-       # * MPropdef: `foo(e)`
-       var html_name: String is lazy do return name.html_escape
-
-       # Returns the MEntity full_name escaped for html.
-       var html_full_name: String is lazy do return full_name.html_escape
-
-       # Link to MEntity in the web server.
-       # TODO this should be parameterizable... but how?
-       fun html_link: Link do return new Link("/doc/{full_name}", html_name)
-
-       # Returns the list of keyword used in `self` declaration.
-       fun html_modifiers: Array[String] is abstract
-
-       # Returns the complete MEntity declaration decorated with HTML.
-       #
-       # * MPackage: `package foo`
-       # * MGroup: `group foo`
-       # * MModule: `module foo`
-       # * MClass: `private abstract class Foo[E: Object]`
-       # * MClassDef: `redef class Foo[E]`
-       # * MProperty: `private fun foo(e: Object): Int`
-       # * MPropdef: `redef fun foo(e)`
-       fun html_declaration: Template do
-               var tpl = new Template
-               tpl.add "<span>"
-               tpl.add html_modifiers.join(" ")
-               tpl.add " "
-               tpl.add html_link
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns `self` namespace decorated with HTML links.
-       #
-       # * MPackage: `mpackage`
-       # * MGroup: `mpackage(::group)`
-       # * MModule: `mgroup::mmodule`
-       # * MClass: `mpackage::mclass`
-       # * MClassDef: `mmodule::mclassdef`
-       # * MProperty: `mclass::mprop`
-       # * MPropdef: `mclassdef:mpropdef`
-       fun html_namespace: Template is abstract
-
-       # Returns the synopsis and the comment of this MEntity formatted as HTML.
-       var html_documentation: nullable Writable is lazy do
-               var mdoc = mdoc_or_fallback
-               if mdoc == null then return null
-               return mdoc.html_documentation
-       end
-
-       # Returns the synopsis of this MEntity formatted as HTML.
-       var html_synopsis: nullable Writable is lazy do
-               var mdoc = mdoc_or_fallback
-               if mdoc == null then return null
-               return mdoc.html_synopsis
-       end
-
-       # Returns the the comment without the synopsis formatted as HTML.
-       var html_comment: nullable Writable is lazy do
-               var mdoc = mdoc_or_fallback
-               if mdoc == null then return null
-               return mdoc.html_comment
-       end
-
-       # Icon that will be displayed before the title
-       fun html_icon: BSIcon do
-               var icon = new BSIcon("tag")
-               icon.css_classes.add_all(css_classes)
-               return icon
-       end
-
-       # CSS classes used to decorate `self`.
-       #
-       # Mainly used for icons.
-       var css_classes = new Array[String]
-end
-
-redef class MPackage
-       redef var html_modifiers = ["package"]
-       redef fun html_namespace do return html_link
-       redef var css_classes = ["public"]
-end
-
-redef class MGroup
-       redef var html_modifiers = ["group"]
-
-       # Depends if `self` is root or not.
-       #
-       # * If root `mpackage`.
-       # * Else `mpackage::self`.
-       redef fun html_namespace do
-               var tpl = new Template
-               tpl.add mpackage.html_namespace
-               if mpackage.root != self then
-                       tpl.add "::"
-                       tpl.add html_link
-               end
-               return tpl
-       end
-
-       redef var css_classes = ["public"]
-end
-
-redef class MModule
-
-       redef var html_modifiers = ["module"]
-
-       # Depends if `self` belongs to a MGroup.
-       #
-       # * If mgroup `mgroup::self`.
-       # * Else `self`.
-       redef fun html_namespace do
-               var mgroup = self.mgroup
-               var tpl = new Template
-               if mgroup != null then
-                       tpl.add mgroup.html_namespace
-                       tpl.add "::"
-               end
-               tpl.add html_link
-               return tpl
-       end
-
-       redef var css_classes = ["public"]
-end
-
-redef class MClass
-       # Format: `Foo[E]`
-       redef var html_name is lazy do
-               var tpl = new Template
-               tpl.add name.html_escape
-               if arity > 0 then
-                       tpl.add "["
-                       var parameter_names = new Array[String]
-                       for p in mparameters do
-                               parameter_names.add(p.html_name)
-                       end
-                       tpl.add parameter_names.join(", ")
-                       tpl.add "]"
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun html_modifiers do return intro.html_modifiers
-       redef fun html_declaration do return intro.html_declaration
-
-       # Returns `mpackage::self`.
-       redef fun html_namespace do
-               var mgroup = intro_mmodule.mgroup
-               var tpl = new Template
-               if mgroup != null then
-                       tpl.add mgroup.mpackage.html_namespace
-                       tpl.add "::"
-               end
-               tpl.add "<span>"
-               tpl.add html_link
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns `intro.html_short_signature`.
-       fun html_short_signature: Template do return intro.html_short_signature
-
-       # Returns `intro.html_signature`.
-       fun html_signature: Template do return intro.html_signature
-
-       redef fun html_icon do return intro.html_icon
-       redef fun css_classes do return intro.css_classes
-end
-
-redef class MClassDef
-       # Depends if `self` is an intro or not.
-       #
-       # * If intro contains the visibility and kind.
-       # * If redef contains the `redef` keyword and kind.
-       redef fun html_modifiers do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       if mclass.visibility != public_visibility then
-                               res.add mclass.visibility.to_s
-                       end
-               end
-               res.add mclass.kind.to_s
-               return res
-       end
-
-       # Depends if `self` is an intro or not.
-       #
-       # For intro: `private abstract class Foo[E: Object]`
-       # For redef: `redef class Foo[E]`
-       redef fun html_declaration do
-               var tpl = new Template
-               tpl.add "<span>"
-               tpl.add html_modifiers.join(" ")
-               tpl.add " "
-               tpl.add html_link
-               if is_intro then
-                       tpl.add html_signature
-               else
-                       tpl.add html_short_signature
-               end
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns `mmodule::self`
-       redef fun html_namespace do
-               var tpl = new Template
-               tpl.add mmodule.html_namespace
-               tpl.add "::<span>"
-               tpl.add mclass.html_link
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns the MClassDef generic signature without static bounds.
-       fun html_short_signature: Template do
-               var tpl = new Template
-               var mparameters = mclass.mparameters
-               if not mparameters.is_empty then
-                       tpl.add "["
-                       for i in [0..mparameters.length[ do
-                               tpl.add mparameters[i].html_name
-                               if i < mparameters.length - 1 then tpl.add ", "
-                       end
-                       tpl.add "]"
-               end
-               return tpl
-       end
-
-       # Returns the MClassDef generic signature with static bounds.
-       fun html_signature: Template do
-               var tpl = new Template
-               var mparameters = mclass.mparameters
-               if not mparameters.is_empty then
-                       tpl.add "["
-                       for i in [0..mparameters.length[ do
-                               tpl.add "{mparameters[i].html_name}: "
-                               tpl.add bound_mtype.arguments[i].html_signature
-                               if i < mparameters.length - 1 then tpl.add ", "
-                       end
-                       tpl.add "]"
-               end
-               return tpl
-       end
-
-       redef fun css_classes do
-               var set = new HashSet[String]
-               if is_intro then set.add "intro"
-               for m in mclass.intro.modifiers do set.add m.to_cmangle
-               for m in modifiers do set.add m.to_cmangle
-               return set.to_a
-       end
-
-
-       # List of all modifiers like redef, private etc.
-       var modifiers: Array[String] is lazy do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       res.add mclass.visibility.to_s
-               end
-               res.add mclass.kind.to_s
-               return res
-       end
-end
-
-redef class MProperty
-       redef fun html_modifiers do return intro.html_modifiers
-       redef fun html_declaration do return intro.html_declaration
-
-       # Returns `mclass::self`.
-       redef fun html_namespace do
-               var tpl = new Template
-               tpl.add intro_mclassdef.mclass.html_namespace
-               tpl.add "::<span>"
-               tpl.add intro.html_link
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns `intro.html_short_signature`.
-       fun html_short_signature: Template do return intro.html_short_signature
-
-       # Returns `intro.html_signature`.
-       fun html_signature: Template do return intro.html_signature
-
-       redef fun css_classes do return intro.css_classes
-end
-
-redef class MPropDef
-       # Depends if `self` is an intro or not.
-       #
-       # * If intro contains the visibility and kind.
-       # * If redef contains the `redef` keyword and kind.
-       redef fun html_modifiers do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       if mproperty.visibility != public_visibility then
-                               res.add mproperty.visibility.to_s
-                       end
-               end
-               return res
-       end
-
-       # Depends if `self` is an intro or not.
-       #
-       # For intro: `private fun foo(e: Object): Bar is abstract`
-       # For redef: `redef fun foo(e) is cached`
-       redef fun html_declaration do
-               var tpl = new Template
-               tpl.add "<span>"
-               tpl.add html_modifiers.join(" ")
-               tpl.add " "
-               if is_intro then
-                       tpl.add html_link
-                       tpl.add html_signature
-               else
-                       tpl.add mproperty.intro.html_link
-                       tpl.add html_short_signature
-               end
-               tpl.add "</span>"
-               return tpl
-       end
-
-       # Returns `mclassdef::self`
-       redef fun html_namespace do
-               var tpl = new Template
-               tpl.add mclassdef.html_namespace
-               tpl.add "::"
-               tpl.add html_link
-               return tpl
-       end
-
-       # Returns the MPropdDef signature without static types.
-       fun html_short_signature: Template is abstract
-
-       # Returns the MPropDef signature with static types.
-       fun html_signature: Template is abstract
-
-       redef fun css_classes do
-               var set = new HashSet[String]
-               if is_intro then set.add "intro"
-               for m in mproperty.intro.modifiers do set.add m.to_cmangle
-               for m in modifiers do set.add m.to_cmangle
-               return set.to_a
-       end
-
-       # List of all modifiers like redef, private, abstract, intern, fun etc.
-       var modifiers: Array[String] is lazy do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       res.add mproperty.visibility.to_s
-               end
-               var mprop = self
-               if mprop isa MVirtualTypeDef then
-                       res.add "type"
-               else if mprop isa MMethodDef then
-                       if mprop.is_abstract then
-                               res.add "abstract"
-                       else if mprop.is_intern then
-                               res.add "intern"
-                       end
-                       if mprop.mproperty.is_init then
-                               res.add "init"
-                       else
-                               res.add "fun"
-                       end
-               end
-               return res
-       end
-end
-
-redef class MAttributeDef
-
-       redef fun html_modifiers do
-               var res = super
-               res.add "var"
-               return res
-       end
-
-       redef fun html_short_signature do return new Template
-
-       redef fun html_signature do
-               var static_mtype = self.static_mtype
-               var tpl = new Template
-               if static_mtype != null then
-                       tpl.add ": "
-                       tpl.add static_mtype.html_signature
-               end
-               return tpl
-       end
-end
-
-redef class MMethodDef
-
-       # FIXME annotation should be handled in their own way
-       redef fun html_modifiers do
-               if mproperty.is_init then
-                       var res = new Array[String]
-                       if mproperty.visibility != public_visibility then
-                               res.add mproperty.visibility.to_s
-                       end
-                       return res
-               end
-               var res = super
-               if is_abstract then
-                       res.add "abstract"
-               else if is_intern then
-                       res.add "intern"
-               end
-               res.add "fun"
-               return res
-       end
-
-       redef fun html_declaration do
-               if mproperty.is_init then
-                       var tpl = new Template
-                       tpl.add "<span>"
-                       tpl.add html_modifiers.join(" ")
-                       tpl.add " "
-                       tpl.add html_link
-                       tpl.add html_signature
-                       tpl.add "</span>"
-                       return tpl
-               end
-               return super
-       end
-
-       redef fun html_short_signature do
-               var new_msignature = self.new_msignature
-               if mproperty.is_root_init and new_msignature != null then
-                       return new_msignature.html_short_signature
-               end
-               return msignature.as(not null).html_short_signature
-       end
-
-       redef fun html_signature do
-               var new_msignature = self.new_msignature
-               if mproperty.is_root_init and new_msignature != null then
-                       return new_msignature.html_signature
-               end
-               return msignature.as(not null).html_signature
-       end
-end
-
-redef class MVirtualTypeProp
-       redef fun html_link do return mvirtualtype.html_link
-end
-
-redef class MVirtualTypeDef
-
-       redef fun html_modifiers do
-               var res = super
-               res.add "type"
-               return res
-       end
-
-       redef fun html_short_signature do return new Template
-
-       redef fun html_signature do
-               var bound = self.bound
-               var tpl = new Template
-               if bound == null then return tpl
-               tpl.add ": "
-               tpl.add bound.html_signature
-               return tpl
-       end
-end
-
-redef class MType
-       # Returns the signature of this type whithout bounds.
-       fun html_short_signature: Template is abstract
-
-       # Returns the signature of this type.
-       fun html_signature: Template is abstract
-end
-
-redef class MClassType
-       redef fun html_link do return mclass.html_link
-       redef fun html_short_signature do return html_link
-       redef fun html_signature do return html_link
-end
-
-redef class MNullableType
-       redef fun html_short_signature do
-               var tpl = new Template
-               tpl.add "nullable "
-               tpl.add mtype.html_short_signature
-               return tpl
-       end
-
-       redef fun html_signature do
-               var tpl = new Template
-               tpl.add "nullable "
-               tpl.add mtype.html_signature
-               return tpl
-       end
-end
-
-redef class MGenericType
-       redef fun html_short_signature do
-               var lnk = html_link
-               var tpl = new Template
-               tpl.add new Link(lnk.href, mclass.name.html_escape, lnk.title)
-               tpl.add "["
-               for i in [0..arguments.length[ do
-                       tpl.add arguments[i].html_short_signature
-                       if i < arguments.length - 1 then tpl.add ", "
-               end
-               tpl.add "]"
-               return tpl
-       end
-
-       redef fun html_signature do
-               var lnk = html_link
-               var tpl = new Template
-               tpl.add new Link(lnk.href, mclass.name.html_escape, lnk.title)
-               tpl.add "["
-               for i in [0..arguments.length[ do
-                       tpl.add arguments[i].html_signature
-                       if i < arguments.length - 1 then tpl.add ", "
-               end
-               tpl.add "]"
-               return tpl
-       end
-end
-
-redef class MParameterType
-       redef fun html_short_signature do return html_link
-       redef fun html_signature do return html_link
-end
-
-redef class MVirtualType
-       redef fun html_signature do return html_link
-end
-
-redef class MSignature
-       redef fun html_short_signature do
-               var tpl = new Template
-               if not mparameters.is_empty then
-                       tpl.add "("
-                       for i in [0..mparameters.length[ do
-                               tpl.add mparameters[i].html_short_signature
-                               if i < mparameters.length - 1 then tpl.add ", "
-                       end
-                       tpl.add ")"
-               end
-               return tpl
-       end
-
-       redef fun html_signature do
-               var tpl = new Template
-               if not mparameters.is_empty then
-                       tpl.add "("
-                       for i in [0..mparameters.length[ do
-                               tpl.add mparameters[i].html_signature
-                               if i < mparameters.length - 1 then tpl.add ", "
-                       end
-                       tpl.add ")"
-               end
-               var return_mtype = self.return_mtype
-               if return_mtype != null then
-                       tpl.add ": "
-                       tpl.add return_mtype.html_signature
-               end
-               return tpl
-       end
-end
-
-redef class MParameter
-
-       # Returns `self` name and ellipsys if any.
-       fun html_short_signature: Template do
-               var tpl = new Template
-               tpl.add name
-               if is_vararg then tpl.add "..."
-               return tpl
-       end
-
-       # Returns `self` name with it's static type and ellipsys if any.
-       fun html_signature: Template do
-               var tpl = new Template
-               tpl.add "{name}: "
-               tpl.add mtype.html_signature
-               if is_vararg then tpl.add "..."
-               return tpl
-       end
-end
-
-redef class MEntityTree
-       # Render `self` as a hierarchical UnorderedList.
-       fun html_list: UnorderedList do
-               var lst = new_unordered_list
-               for r in roots do
-                       var li = new_mentity_item(r)
-                       lst.add_li li
-                       build_html_list(r, li)
-               end
-               return lst
-       end
-
-       # Build the html list recursively.
-       private fun build_html_list(e: MEntity, li: ListItem) do
-               if not sub.has_key(e) then return
-               var subs = sub[e]
-               var lst = new_unordered_list
-               for e2 in subs do
-                       if e2 isa MGroup and e2.is_root then
-                               build_html_list(e2, li)
-                       else
-                               var sli = new_mentity_item(e2)
-                               lst.add_li sli
-                               build_html_list(e2, sli)
-                       end
-               end
-               var text = new Template
-               text.add li.text
-               if not lst.is_empty then text.add lst
-               li.text = text
-       end
-
-       # HTML unordered List used to compose the tree.
-       #
-       # Redefine this method to add custom CSS classes or other html attributes.
-       protected fun new_unordered_list: UnorderedList do return new UnorderedList
-
-       # Return a li element for `mconcern` that can be displayed in a concern list
-       protected fun new_mentity_item(mentity: MEntity): ListItem do
-               var tpl = new Template
-               tpl.add mentity.html_link
-               var comment = mentity.html_synopsis
-               if comment != null then
-                       tpl.add ": "
-                       tpl.add comment
-               end
-               return new ListItem(tpl)
-       end
-end
similarity index 85%
rename from src/doc/doc.nit
rename to src/doc/static/static.nit
index a6fb971..c1a51f5 100644 (file)
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Nitdoc generation framework.
-module doc
+# Nitdoc generation framework
+module static
 
-import doc_base
-import doc_phases
+import static::static_html
+import static::static_index
diff --git a/src/doc/static/static_base.nit b/src/doc/static/static_base.nit
new file mode 100644 (file)
index 0000000..16f09aa
--- /dev/null
@@ -0,0 +1,350 @@
+# 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.
+
+# Base entities shared by all the nitdoc code
+module static_base
+
+import static_cards
+import modelize
+
+# The model of a Nitdoc documentation
+class DocModel
+
+       # Model used to select entities
+       var model: Model
+
+       # Mainmodule to resolve linearization
+       var mainmodule: MModule
+
+       # ModelBuilder used to retrieve AST nodes
+       var modelbuilder: ModelBuilder
+
+       # Catalog for building the homepage
+       var catalog: Catalog
+
+       # Model filters applied to the whole documentation
+       var filter: ModelFilter
+
+       # Specific Markdown processor to use within Nitdoc
+       var md_processor: MarkdownProcessor is lazy do
+               var parser = new CommandParser(model, mainmodule, modelbuilder, catalog)
+               var proc = new CmdMarkdownProcessor(parser)
+               proc.decorator = new CmdDecorator(model)
+               return proc
+       end
+
+       # Specific Markdown processor to use within Nitdoc
+       var inline_processor: MarkdownProcessor is lazy do
+               var parser = new CommandParser(model, mainmodule, modelbuilder, catalog)
+               var proc = new CmdMarkdownProcessor(parser)
+               proc.decorator = new CmdInlineDecorator(model)
+               return proc
+       end
+
+       # Do not generate dot graphs
+       var no_dot = false is writable
+
+       # Do not generate higlighted code
+       var no_code = false is writable
+
+       # Url to code when `no_code` is true
+       var code_url: nullable String = null is writable
+
+       # Url to assets
+       var share_url: nullable String = null is writable
+
+       # Custom menu brand
+       var custom_brand: nullable String = null is writable
+
+       # Custom homepage title
+       var custom_title: nullable String = null is writable
+
+       # Custom page footer
+       var custom_footer: nullable String = null is writable
+
+       # Custom homepage intro text
+       var custom_intro: nullable String = null is writable
+
+       # Optional tracker url
+       var tracker_url: nullable String = null is writable
+
+       # Optional tracker site id
+       var piwik_site_id: nullable String = null is writable
+
+       # Used to sort sidebar elements by name.
+       var name_sorter = new MEntityNameSorter
+end
+
+# Documentation pages
+
+# A documentation page abstraction
+class DocPage
+
+       # Title of this page
+       var title: String is writable
+
+       # Page tab panels
+       #
+       # Nitdoc pages are tabulated.
+       # If a page has only one tab, it is presented as a single page.
+       # With more than one tab, the HTML rendering process adds tab headers and
+       # links.
+       var tabs: Array[DocTab] = [main_tab] is lazy
+
+       # The page main tab
+       #
+       # For most pages this tab is suffisent.
+       # Subclasses can add more tabs.
+       var main_tab = new DocTab("main", "Main")
+
+       redef fun to_s do return title
+end
+
+# The Nitdoc overview page that displays the nit packages catalog
+class PageHome
+       super DocPage
+end
+
+# A DocPage documenting a MEntity
+abstract class PageMEntity
+       super DocPage
+       autoinit mentity
+
+       new(mentity: MEntity) do
+               if mentity isa MPackage then
+                       return new PageMPackage(mentity)
+               else if mentity isa MGroup then
+                       return new PageMGroup(mentity)
+               else if mentity isa MModule then
+                       return new PageMModule(mentity)
+               else if mentity isa MClass then
+                       return new PageMClass(mentity)
+               else if mentity isa MProperty then
+                       return new PageMProperty(mentity)
+               else
+                       print "Not yet implemented: Page for {mentity.full_name} ({mentity.class_name})"
+                       abort
+               end
+       end
+
+       # Type of MEntity documented by this page
+       type MENTITY: MEntity
+
+       # MEntity documented by this page
+       var mentity: MENTITY
+
+       # For mentities the main tab is the doc tab
+       redef var main_tab = new DocTab("doc", "Doc", true, "book")
+
+       # API tab
+       #
+       # Where the MEntity API (groups, modules, classes, props) is displayed
+       var api_tab = new DocTab("api", "API", false, "list")
+
+       # Dependencies tab
+       #
+       # Where the MEntity importation or inheritance is displayed
+       var dep_tab = new DocTab("inh", "Dependencies", false, "object-align-vertical")
+
+       # Code tab
+       #
+       # Since all mentities does not have code, this tab in not in the `tabs` list
+       # by default.
+       var code_tab = new DocTab("code", "Code", false, "console")
+
+       # Lienarization tab
+       #
+       # Since all mentities does not have a linearization, this tab in not in the
+       # `tabs` list by default.
+       var lin_tab = new DocTab("lin", "Linearization", false, "arrow-down")
+
+       redef var tabs = [main_tab, api_tab, dep_tab] is lazy
+       redef var title is lazy do return mentity.name
+end
+
+# A documentation page for a MPackage
+class PageMPackage
+       super PageMEntity
+
+       redef type MENTITY: MPackage
+       redef var api_tab = new DocTab("api", "Groups & Modules", false, "list")
+end
+
+# A documentation page about a MGroup
+class PageMGroup
+       super PageMEntity
+
+       redef type MENTITY: MGroup
+       redef var api_tab = new DocTab("api", "Subgroups & Modules", false, "list")
+end
+
+# A documentation page about a MModule
+class PageMModule
+       super PageMEntity
+
+       redef type MENTITY: MModule
+       redef var api_tab = new DocTab("api", "Classes", false, "list")
+       redef var dep_tab = new DocTab("inh", "Importation", false, "object-align-vertical")
+       redef var tabs = [main_tab, api_tab, dep_tab, code_tab] is lazy
+end
+
+# A documentation page about a MClass
+class PageMClass
+       super PageMEntity
+
+       redef type MENTITY: MClass
+       redef var api_tab = new DocTab("api", "All properties", false, "list")
+       redef var dep_tab = new DocTab("inh", "Inheritance", false, "object-align-vertical")
+       redef var tabs = [main_tab, api_tab, dep_tab, lin_tab] is lazy
+end
+
+# A documentation page about a MProperty
+class PageMProperty
+       super PageMEntity
+
+       redef type MENTITY: MProperty
+       redef var tabs = [main_tab, lin_tab] is lazy
+end
+
+# A page that lists the packages maintained and contributed by a person
+class PagePerson
+       super DocPage
+       autoinit person
+
+       # Person displayed in this page
+       var person: Person
+
+       redef var title is lazy do return person.name
+end
+
+# A page that lists the packages related to a tab
+class PageTag
+       super DocPage
+       autoinit tag
+
+       # Tag displayed in this page
+       var tag: String
+
+       redef var title is lazy do return tag
+end
+
+# Breadcrumbs
+
+redef class MEntity
+       # MEntities composing the breadcrumbs of a nitdoc page
+       fun nitdoc_breadcrumbs: Array[MEntity] is abstract
+end
+
+redef class MPackage
+       redef var nitdoc_breadcrumbs = [self: MEntity] is lazy
+end
+
+redef class MGroup
+       redef var nitdoc_breadcrumbs is lazy do
+               var parent = self.parent
+               if parent != null then
+                       return parent.nitdoc_breadcrumbs + [self]
+               end
+               return mpackage.nitdoc_breadcrumbs
+       end
+end
+
+redef class MModule
+       redef var nitdoc_breadcrumbs is lazy do
+               var mgroup = self.mgroup
+               if mgroup != null then
+                       return mgroup.nitdoc_breadcrumbs + [self]
+               end
+               return [self]
+       end
+end
+
+redef class MClass
+       redef var nitdoc_breadcrumbs is lazy do
+               return intro_mmodule.nitdoc_breadcrumbs + [self]
+       end
+end
+
+redef class MClassDef
+       redef var nitdoc_breadcrumbs is lazy do
+               var res = new Array[MEntity].from(mmodule.nitdoc_breadcrumbs)
+               res.add self
+               return res
+       end
+end
+
+redef class MProperty
+       redef var nitdoc_breadcrumbs is lazy do
+               var res = new Array[MEntity].from(intro_mclassdef.mclass.nitdoc_breadcrumbs)
+               res.add self
+               return res
+       end
+end
+
+redef class MPropDef
+       redef var nitdoc_breadcrumbs is lazy do
+               var res = new Array[MEntity].from(mclassdef.nitdoc_breadcrumbs)
+               res.add self
+               return res
+       end
+end
+
+# Documentation base elements
+
+# A documentation tabulated view
+class DocTab
+
+       # Tab uniq id in the page
+       var id: String is writable
+
+       # Table title
+       var title: String is writable
+
+       # Is this tab displayed by default?
+       var is_active = false is optional, writable
+
+       # Tab header icon
+       var icon: nullable String = null is optional, writable
+
+       # Tab content
+       var content = new Array[StaticCard]
+
+       # Tab sidebar
+       var sidebar = new DocSidebar
+
+       # Tab metadata sidebar
+       var metadata = new DocSidebar
+
+       # Is this tab empty?
+       fun is_empty: Bool do return content.is_empty
+end
+
+# A fictive tab used to display a link
+class DocTabLink
+       super DocTab
+       autoinit(id, title, icon, url)
+
+       # Link to open when the tab is clicked
+       var url: String
+end
+
+# Nitdoc sidebar abstraction
+class DocSidebar
+
+       # A sidebar contains `StaticCard`
+       var cards = new Array[StaticCard]
+
+       # Is this sidebar empty?
+       fun is_empty: Bool do return cards.is_empty
+end
diff --git a/src/doc/static/static_cards.nit b/src/doc/static/static_cards.nit
new file mode 100644 (file)
index 0000000..c02f565
--- /dev/null
@@ -0,0 +1,675 @@
+# 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.
+
+# Cards templates for the static documentation
+module static_cards
+
+import templates::html_commands
+
+# A card that can be rendered to HTML
+#
+# Basically, these cards are templates with additionnal data and behavior.
+abstract class StaticCard
+       super Template
+
+       # Card title
+       var title: String is writable
+
+       # Card id
+       var id: String is writable
+end
+
+# A list of cards
+class CardList
+       super StaticCard
+
+       # Cards contained in this list
+       var cards = new Array[StaticCard] is writable
+
+       redef fun rendering do
+               addn "<div id='{id}' class='card-list'>"
+               for card in cards do
+                       addn card
+               end
+               addn "</div>"
+       end
+end
+
+# Doc elements
+
+# A card that display custom text data
+class CardText
+       super StaticCard
+       autoinit(content)
+
+       # Custom content from options
+       var content: nullable String is writable
+
+       redef var id = "home"
+       redef var title = "Home"
+
+       redef fun rendering do
+               var content = self.content
+               if content == null then return
+               addn "<div>"
+               addn content
+               addn "</div>"
+               addn "<hr/>"
+       end
+end
+
+# A heading section
+#
+# It displays an heading at a specific level from 1 to 6.
+class CardSection
+       super StaticCard
+       autoinit(level, title, subtitle)
+
+       # Section heading level
+       var level: Int is writable
+
+       # Section subtitle
+       var subtitle: nullable String is writable
+
+       redef var id = title.to_cmangle is lazy
+
+       redef fun rendering do
+               addn "<h{level} id='{id}'>{title}</h{level}>"
+       end
+end
+
+# A page header
+class CardPageHeader
+       super CardSection
+       autoinit(title, subtitle)
+
+       redef var level = 2
+
+       redef fun rendering do
+               addn "<div class='page-header'>"
+               super
+               var subtitle = self.subtitle
+               if subtitle != null then
+                       addn "<p class='text-muted'>"
+                       addn subtitle
+                       addn "</p>"
+               end
+               addn "</div>"
+       end
+end
+
+# A card that displays a summary of a list of cards
+class CardSummary
+       super CardList
+       autoinit(no_title)
+
+       redef var id = "summary"
+       redef var title = "Summary"
+
+       # Show the summary title
+       var no_title: Bool = false is optional, writable
+
+       redef fun rendering do
+               if not no_title then
+                       addn "<h4>Summary</h4>"
+               end
+               addn "<div class='summary'>"
+               addn " <ul class='list-unstyled'>"
+               var sections = new Array[CardSection]
+               for card in cards do
+                       if card isa CardSection then
+                               while sections.not_empty and sections.last.level >= card.level do
+                                       sections.pop
+                               end
+                               sections.add card
+                       end
+                       var level = if sections.is_empty then 1 else sections.last.level
+                       if not card isa CardSection then level += 1
+                       addn "<li><a href='#{card.id}'><h{level}>{card.title}</h{level}></a></li>"
+               end
+               addn " </ul>"
+               addn "</div>"
+       end
+end
+
+# A card that displays the summary of a Markdown document
+class CardMdSummary
+       super CardMDoc
+       autoinit(md_processor, headlines)
+
+       # Markdown processor used to extract and render the content
+       var md_processor: MarkdownProcessor is writable
+
+       # Headlines found in the document
+       var headlines: ArrayMap[String, HeadLine] is writable
+
+       redef var id = "summary"
+       redef var title = "Summary"
+
+       redef fun rendering do
+               addn "<h4>Summary</h4>"
+               addn "<div class='summary'>"
+               addn " <ul class='list-unstyled'>"
+               for id, headline in headlines do
+                       var level = headline.level
+                       var title = md_processor.process(headline.title)
+                       addn "<li><a href='#{id}'><h{level}>{title}</h{level}></a></li>"
+               end
+               addn " </ul>"
+               addn "</div>"
+       end
+end
+
+# MEntity related cards
+
+# A card about a mentity
+#
+# It displays the documentation about the model entity.
+class CardMEntity
+       super StaticCard
+       autoinit(mentity, full_doc)
+
+       # MEntity displayed in this card
+       var mentity: MEntity is writable
+
+       # Render the mentity full documentation?
+       var full_doc = false is optional, writable
+
+       redef var id = mentity.html_id is lazy
+       redef var title = mentity.html_name is lazy
+
+       redef fun rendering do
+               addn """
+               <div id='{{{id}}}' class='card'>
+                       <div class='card-left text-center'>
+                       {{{mentity.html_icon.write_to_string}}}
+                       </div>
+                       <div class='card-body'>
+                               <h5 class='card-heading'>
+                                       {{{mentity.html_declaration.write_to_string}}}
+                               </h5>
+                               <p><small>{{{mentity.html_namespace.write_to_string}}}</small></p>"""
+               var mdoc = mentity.mdoc_or_fallback
+               if mdoc != null then
+                       if full_doc then
+                               addn mdoc.html_documentation
+                       else
+                               addn mdoc.html_synopsis
+                       end
+               end
+               addn """
+                       </div>
+               </div>"""
+       end
+end
+
+# A card that displays the content of a MDoc
+class CardMDoc
+       super CardMEntity
+       autoinit(mentity, mdoc, full_doc)
+
+       # MDoc to display in this card
+       var mdoc: nullable MDoc is writable
+
+       redef fun rendering do
+               var mdoc = self.mdoc
+               if mdoc == null then return
+               addn "<div id='{id}' class='card'>"
+               addn " <div class='card-body nitdoc'>"
+               addn mdoc.html_documentation
+               addn " </div>"
+               addn "</div>"
+       end
+end
+
+# A card about the inheritance of a MEntity
+class CardInheritance
+       super CardMEntity
+
+       # Ancestors list
+       var ancestors: nullable Array[MEntity] is writable
+
+       # Parents list
+       var parents: nullable Array[MEntity] is writable
+
+       # Children list
+       var children: nullable Array[MEntity] is writable
+
+       # Descendants list
+       var descendants: nullable Array[MEntity] is writable
+
+       redef var id = "inh_{super}" is lazy
+       redef var title = "Inheritance" is lazy
+
+       redef fun rendering do
+               var ancestors = self.ancestors
+               var descendants = self.descendants
+               if ancestors == null and parents == null and
+                       children == null and descendants == null then return
+
+               addn "<div id='{id}' class='card'>"
+               addn " <div class='card-body'>"
+               if ancestors != null and ancestors.length <= 10 then
+                       render_list("Ancestors", ancestors)
+               else
+                       render_list("Parents", parents)
+               end
+               if descendants != null and descendants.length <= 10 then
+                       render_list("Descendants", descendants)
+               else
+                       render_list("Children", children)
+               end
+               addn " </div>"
+               addn "</div>"
+       end
+
+       private fun render_list(title: String, mentities: nullable Array[MEntity]) do
+               if mentities == null or mentities.is_empty then return
+               addn "<h4 id='{id}'>{title}</h4>"
+               addn "<ul class='list-unstyled'>"
+               for mentity in mentities do
+                       addn html_list_item(mentity)
+               end
+               addn "</ul>"
+       end
+
+       private fun html_list_item(mentity: MEntity): ListItem do
+               var tpl = new Template
+               tpl.add mentity.html_namespace
+               var comment = mentity.mdoc_or_fallback
+               if comment != null then
+                       tpl.add ": "
+                       tpl.add comment.html_synopsis
+               end
+               return new ListItem(tpl)
+       end
+end
+
+# A card about the linearization of a MEntity
+class CardLinearizationList
+       super CardMEntity
+
+       # Linearization cards contained in this list
+       var cards = new Array[CardLinearizationDef] is writable
+
+       redef var id = "lin_{super}" is lazy
+       redef var title = "Linearization" is lazy
+
+       redef fun rendering do
+               if cards.is_empty then return
+
+               addn "<div id='{id}'>"
+               for card in cards do
+                       addn card
+                       if card == cards.last then break
+                       addn "<h4 class='text-muted text-center'>"
+                       addn " <span class='glyphicon glyphicon-chevron-up'></span>"
+                       addn "</h4>"
+               end
+               addn "</div>"
+       end
+end
+
+# A card about a definition in a linearization list
+class CardLinearizationDef
+       super CardCode
+
+       # Is this card displayed by default?
+       var is_active: Bool = false is optional, writable
+
+       # Link to external code repository
+       #
+       # Used if `node` is null
+       var url: nullable String = null is optional, writable
+
+       redef var id = "def_{super}" is lazy
+       redef var title = mentity.full_name is lazy
+
+       redef fun rendering do
+               var url = self.url
+
+               var cin = if is_active then "in" else ""
+               var active = if is_active then "active" else ""
+               addn """
+               <div class='card {{{active}}}' id='{{{id}}}'>
+                       <div class='card-body'>
+                               <h5>
+                                       {{{mentity.html_icon.write_to_string}}}
+                                       {{{mentity.html_namespace.write_to_string}}}"""
+               if node != null then
+                       addn """
+                                       <div class='btn-bar'>
+                                               <button class='btn btn-link' data-toggle='collapse'
+                                                 data-target='#{{{mentity.html_id}}}'>
+                                                       <span class='glyphicon glyphicon-console' title='Show code' />
+                                               </button>
+                                       </div>"""
+               else if url != null then
+                       addn """
+                                       <div class='btn-bar'>
+                                               <a class='btn btn-link' href='{{{url}}}'>
+                                                       <span class='glyphicon glyphicon-console' title='Show code' />
+                                               </a>
+                                       </div>"""
+                       var mdoc = mentity.mdoc
+                       if mdoc != null then
+                               addn "<br/><br/>"
+                               addn mdoc.html_documentation
+                       end
+               end
+               addn "</h5>"
+               if node != null then
+                       addn """
+                               <div id='{{{mentity.html_id}}}' class='collapse {{{cin}}}'>
+                                       <pre>"""
+                       render_code
+                       addn """</pre>
+                                       <span class='text-muted'>{{{mentity.location.to_s}}}</span>
+                               </div>"""
+               end
+               addn """
+                       </div>
+               </div>"""
+       end
+end
+
+# A card that displays the code of a MEntity
+class CardCode
+       super CardMEntity
+       autoinit(mentity, node)
+
+       # AST node to display in this card
+       var node: nullable ANode is writable
+
+       redef var id = "code_{super}" is lazy
+       redef var title = "Code"
+
+       redef fun rendering do
+               addn "<div id='{id}' class='card'>"
+               addn " <div class='card-body'>"
+
+               if node != null then
+                       addn "<pre>"
+                       render_code
+                       addn "</pre>"
+               end
+               addn "<span class='text-muted'>{mentity.location}</span>"
+
+               addn " </div>"
+               addn "</div>"
+       end
+
+       private fun render_code do
+               var node = self.node
+               if node == null then return
+               var hl = new HtmlightVisitor
+               hl.show_infobox = false
+               hl.highlight_node node
+               addn hl.html
+       end
+end
+
+# A card that displays a graph
+class CardGraph
+       super CardMEntity
+       autoinit(mentity, graph)
+
+       # Graph to display in this card
+       var graph: InheritanceGraph is writable
+
+       redef var id = "graph_{super}" is lazy
+       redef var title = "Graph"
+
+       redef fun rendering do
+               addn "<div id='{id}' class='card'>"
+               addn " <div class='card-body'>"
+               addn "  <div class='text-center'>"
+               addn graph.graph.to_svg
+               addn "  </div>"
+               addn " </div>"
+               addn "</div>"
+       end
+end
+
+# Catalog related cards
+
+# A card that displays Nit catalog related data
+abstract class CardCatalog
+       super StaticCard
+       autoinit(catalog)
+
+       # Catalog used to extract the data
+       var catalog: Catalog is writable
+end
+
+# A card that displays statistics about a Nit catalog
+class CardCatalogStats
+       super CardCatalog
+
+       redef var id = "catalog_stats"
+       redef var title = "Stats"
+
+       redef fun rendering do
+               addn "<div id='{id}' class='container-fluid'>"
+               for key, value in catalog.catalog_stats.to_map do
+                       addn "<span class='text-muted small'>"
+                       addn " <strong>{value}</strong>&nbsp;<span>{key}</span>&nbsp;"
+                       addn "</span>"
+               end
+               addn "</div>"
+               addn "<hr/>"
+       end
+end
+
+# A card that displays a list of tags
+class CardCatalogTags
+       super CardCatalog
+
+       redef var id = "catalog_tags"
+       redef var title = "Tags"
+
+       # Sorter to sort tags alphabetically
+       var tags_sorter = new CatalogTagsSorter is writable
+
+       redef fun rendering do
+               var tags = catalog.tag2proj.keys.to_a
+               if tags.is_empty then return
+               tags_sorter.sort(tags)
+
+               addn "<h2 id='{id}'>Tags</h2>"
+               addn "<div class='container-fluid'>"
+               for tag in tags do
+                       addn "<div class='col-xs-6 col-sm-3 col-md-2'>"
+                       addn " <span class='badge'>{catalog.tag2proj[tag].length}</span>"
+                       addn " <a href='tag_{tag.to_cmangle}.html'>{tag}</a>"
+                       addn "</div>"
+               end
+               addn "</div>"
+               addn "<hr/>"
+       end
+end
+
+# A card that displays a package from a Nit catalog
+class CardCatalogPackage
+       super CardCatalog
+       super CardMEntity
+       autoinit(catalog, mentity)
+
+       redef var id = "package_{super}" is lazy
+
+       redef fun rendering do
+               var mpackage = self.mentity
+               if not mpackage isa MPackage then return
+
+               addn """
+                       <div id='{{{id}}}' class='card'>
+                        <div class='card-left text-center'>{{{mpackage.html_icon.write_to_string}}}</div>
+                        <div class='card-body' style='width: 75%'>
+                         <h5 class='card-heading'>
+                               {{{mentity.html_declaration.write_to_string}}}
+                               <small>&nbsp;"""
+               for tag in mpackage.metadata.tags do
+                       add "<span>"
+                       add "<a href='tag_{tag.to_cmangle}.html' class='text-muted'>{tag}</a>"
+                       if tag != mpackage.metadata.tags.last then addn ", "
+                       add "</span>"
+               end
+               addn """</small>
+                               </h5>"""
+               var mdoc = mentity.mdoc_or_fallback
+               if mdoc != null then
+                       if full_doc then
+                               addn mdoc.html_documentation
+                       else
+                               addn mdoc.html_synopsis
+                       end
+               end
+               addn " </div>"
+               addn " <div class='card-right' style='width: 25%'>"
+               for maintainer in mpackage.metadata.maintainers do
+                       addn maintainer.to_html
+               end
+               addn " <br>"
+               var license = mpackage.metadata.license
+               if license != null then
+                       addn """
+                                <span class='text-muted'>
+                                 <a href='http://opensource.org/licenses/{{{license}}}' class='text-muted'>
+                                  {{{license}}}
+                                 </a>
+                               </span>"""
+               end
+               addn " </div>"
+               addn "</div>"
+       end
+end
+
+# A card that displays the metadata about a package in the Nit catalog
+class CardMetadata
+       super CardMEntity
+       autoinit(mentity, metadata, stats, deps, clients)
+
+       # Package metadata to display
+       var metadata: MPackageMetadata is writable
+
+       # Package stats
+       var stats: MPackageStats is writable
+
+       # Package dependencies
+       var deps: Array[MPackage] is writable
+
+       # Package clients
+       var clients: Array[MPackage] is writable
+
+       redef var id = "metadata_{super}" is lazy
+       redef var title = "Metadata"
+
+       redef fun rendering do
+               for maintainer in metadata.maintainers do
+                       addn """
+                               <p class='lead'>
+                                       {{{maintainer.to_html}}}
+                               </p>"""
+               end
+               var license = metadata.license
+               if license != null then
+                       addn """
+                               <span class='text-muted'>
+                                       <a href='http://opensource.org/licenses/{{{license}}}'>{{{license}}}</a>
+                                       license
+                               </span>"""
+               end
+
+               var homepage = metadata.homepage
+               var browse = metadata.browse
+               var issues = metadata.issues
+               if homepage != null or browse != null or issues != null then
+                       addn """
+                               <h4>Links</h4>
+                               <ul class='list-unstyled'>"""
+                       if homepage != null then addn "<li><a href='{homepage}'>Homepage</a></li>"
+                       if browse != null then addn "<li><a href='{browse}'>Source Code</a></li>"
+                       if issues != null then addn "<li><a href='{issues}'>Issues</a></li>"
+                       addn "</ul>"
+               end
+
+               var git = metadata.git
+               var last_date = metadata.last_date
+               var first_date = metadata.first_date
+               if git != null then
+                       addn """
+                               <h4>Git</h4>
+                               <ul class='list-unstyled'>
+                                       <li><a href='{{{git}}}'>{{{git}}}</a></li>
+                               </ul>
+                               <span class='text-muted'><b>{{{stats.commits}}}</b> commits</span>
+                               <br>"""
+                       if last_date != null then
+                               addn """<b class=text-muted>Last:</b> {{{last_date}}}<br>"""
+                       end
+                       if first_date != null then
+                               addn """<b class=text-muted>First:</b> {{{first_date}}}"""
+                       end
+               end
+
+               addn """
+                       <h4>Quality</h4>
+                       <ul class='list-unstyled'>
+                               <li>{{{stats.documentation_score}}}% documented</li>
+                       </ul>"""
+
+               if metadata.tags.not_empty then
+                       addn "<h4>Tags</h4>"
+                       for tag in metadata.tags do
+                               addn " <a href='tag_{tag.to_cmangle}.html'>{tag}</a>"
+                               if tag != metadata.tags.last then add ", "
+                       end
+               end
+
+               if deps.not_empty then
+                       addn "<h4>Dependencies</h4>"
+                       for dep in deps do
+                               add dep.html_link
+                               if dep != deps.last then add ", "
+                       end
+               end
+
+               if clients.not_empty then
+                       addn "<h4>Clients</h4>"
+                       for client in clients do
+                               add client.html_link
+                               if client != clients.last then add ", "
+                       end
+               end
+
+               if metadata.contributors.not_empty then
+                       addn """
+                               <h4>Contributors</h4>
+                               <ul class='list-unstyled'>"""
+                       for contrib in metadata.contributors do
+                               addn """<li>{{{contrib.to_html}}}</li>"""
+                       end
+                       addn "</ul>"
+               end
+
+               addn """
+                       <h4>Stats</h4>
+                       <ul class='list-unstyled'>
+                               <li>{{{stats.mmodules}}} modules</li>
+                               <li>{{{stats.mclasses}}} classes</li>
+                               <li>{{{stats.mmethods}}} methods</li>
+                               <li>{{{stats.loc}}} loc</li>
+                       </ul>"""
+       end
+end
diff --git a/src/doc/static/static_html.nit b/src/doc/static/static_html.nit
new file mode 100644 (file)
index 0000000..eb2834f
--- /dev/null
@@ -0,0 +1,412 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Render documentation pages as HTML
+module static_html
+
+import static::static_structure
+import json
+
+redef class DocPage
+       super Template
+
+       # Page url
+       var html_url: String is writable, noinit
+
+       # Directory where css, js and other assets can be found
+       var shareurl: String is writable, noinit
+
+       # Top menu template if any
+       var topmenu: DocTopMenu is writable, noinit
+
+       # Footer content if any
+       var footer: nullable Writable = null is writable
+
+       # Render the page as a html template
+       fun render(doc: DocModel): Writable do
+               # init page options
+               self.shareurl = doc.share_url or else "."
+               self.footer = doc.custom_footer
+
+               # build page
+               init_title(doc)
+               init_topmenu(doc)
+
+               # piwik tracking
+               var tracker_url = doc.tracker_url
+               var site_id = doc.piwik_site_id
+               if tracker_url != null and site_id != null then
+                       piwik_script = new PiwikScript(tracker_url, site_id)
+               end
+               return self
+       end
+
+       # Build page title string
+       fun init_title(doc: DocModel) do end
+
+       # Build top menu template if any
+       fun init_topmenu(doc: DocModel) do
+               topmenu = new DocTopMenu
+
+               var home = new Link("index.html", "Nitdoc")
+
+               var custom_brand = doc.custom_brand
+               if custom_brand != null then
+                       topmenu.brand = new Link("index.html", custom_brand)
+                       topmenu.items.add new ListItem(home)
+               else
+                       topmenu.brand = home
+               end
+       end
+
+       # Renders the html `<head>`
+       private fun render_head do
+               var css = (self.shareurl / "css").html_escape
+               var vendors = (self.shareurl / "vendors").html_escape
+
+               addn "<!DOCTYPE html>"
+               addn "<head>"
+               addn " <meta charset='utf-8'/>"
+               addn " <link rel='stylesheet' href='{vendors}/bootstrap/css/bootstrap.min.css'/>"
+               addn " <link rel='stylesheet' href='{css}/nitdoc.bootstrap.css'/>"
+               addn " <link rel='stylesheet' href='{css}/nitdoc.cards.css'/>"
+               addn " <link rel='stylesheet' href='{css}/nitdoc.code.css'/>"
+               addn " <link rel='stylesheet' href='{css}/nitdoc.css'/>"
+               addn " <link rel='stylesheet' href='{css}/nitdoc.quicksearch.css'/>"
+               addn " <title>{title.html_escape}</title>"
+               addn "</head>"
+               add "<body>"
+       end
+
+       # Renders the footer and content
+       private fun render_content do
+               if tabs.is_empty then return
+               if tabs.length == 1 then
+                       addn tabs.first
+                       return
+               end
+               addn "<ul class='nav nav-tabs'>"
+               for tab in tabs do
+                       if tab.is_empty and not tab isa DocTabLink then continue
+                       addn tab.tab_link
+               end
+               addn "</ul>"
+               addn "<div class='tab-content'>"
+               for tab in tabs do
+                       if tab.is_empty then continue
+                       addn tab
+               end
+               addn "</div>"
+       end
+
+       # Piwik script to append in the page scripts
+       var piwik_script: nullable PiwikScript = null is writable
+
+       # Render JS scripts
+       private fun render_footer do
+               if footer != null then
+                       addn "<div class='footer'>"
+                       add footer.as(not null)
+                       addn "</div>"
+               end
+               var vendors = (self.shareurl / "vendors").html_escape
+               var js = (self.shareurl / "js").html_escape
+
+               addn "<script src='quicksearch-list.js'></script>"
+               addn "<script src='{vendors}/jquery/jquery-1.11.1.min.js'></script>"
+               addn "<script src='{vendors}/jquery/jquery-ui-1.10.4.custom.min.js'></script>"
+               addn "<script src='{vendors}/bootstrap/js/bootstrap.min.js'></script>"
+               addn "<script src='{js}/nitdoc.utils.js'></script>"
+               addn "<script src='{js}/nitdoc.quicksearch.js'></script>"
+
+               var piwik_script = self.piwik_script
+               if piwik_script != null then
+                       add piwik_script
+               end
+               addn "</body>"
+               addn "</html>"
+       end
+
+       # Render the whole page
+       redef fun rendering do
+               render_head
+               add topmenu
+               addn "<div class='container-fluid'>"
+               render_content
+               addn "</div>"
+               render_footer
+       end
+end
+
+redef class PageHome
+       redef var html_url = "index.html"
+
+       redef fun render(doc) do
+               main_tab.show_sidebar = false
+               return super
+       end
+
+       redef fun init_title(doc) do
+               title = doc.custom_title or else "Nitdoc"
+       end
+
+       redef fun render_content do
+               addn "<div class='container'>"
+               if tabs.not_empty then
+                       addn tabs.first
+               end
+               addn "</div>"
+       end
+end
+
+redef class PageMEntity
+       redef var html_url is lazy do return mentity.html_url
+       redef fun init_title(doc) do title = mentity.html_name
+
+       redef fun render_content do
+               addn new CardPageHeader(
+                       mentity.html_declaration.write_to_string,
+                       mentity.html_namespace.write_to_string)
+               super
+       end
+
+       redef fun init_topmenu(doc) do
+               super
+               for m in mentity.nitdoc_breadcrumbs do
+                       topmenu.add_li new ListItem(new Link(m.html_url, m.html_name))
+               end
+               topmenu.active_item = topmenu.items.last
+       end
+end
+
+redef class PagePerson
+       redef var html_url is lazy do return person.html_url
+end
+
+redef class PageTag
+       redef var html_url is lazy do return "tag_{tag.to_cmangle}.html"
+end
+
+redef class HtmlightVisitor
+       redef fun hrefto(mentity) do return mentity.html_url
+end
+
+redef class DocTab
+       super Template
+
+       # Show sidebar for this page?
+       var show_sidebar = true is writable
+
+       # Tab link for tab headers
+       fun tab_link: Template do
+               var tpl = new Template
+               tpl.addn "<li class='{if is_active then "active" else ""}'>"
+               tpl.addn " <a data-toggle='tab' href='#{id}'>"
+
+               var icon = self.icon
+               if icon != null then
+                       tpl.addn "  <span class='glyphicon glyphicon-{icon}'></span>"
+               end
+               tpl.addn " {title}"
+               tpl.addn " </a>"
+               tpl.addn "</li>"
+               return tpl
+       end
+
+       redef fun rendering do
+               var has_left = show_sidebar and sidebar.cards.not_empty
+               var has_right = metadata.cards.not_empty
+
+               addn "<div class='tab-pane {if is_active then "active" else ""}' id='{id}'>"
+               if has_left then
+                       addn " <div class='col-sm-3'>"
+                       addn sidebar
+                       addn " </div>"
+               end
+               var cols = 12
+               if has_left then cols -= 3
+               if has_right then cols -= 3
+               addn " <div class='col-sm-{cols}'>"
+               for card in content do addn card
+               addn " </div>"
+               if has_right then
+                       addn " <div class='col-sm-3'>"
+                       addn metadata
+                       addn " </div>"
+               end
+               addn "</div>"
+       end
+end
+
+redef class DocTabLink
+
+       redef fun tab_link do
+               var tpl = new Template
+               tpl.addn "<li class='{if is_active then "active" else ""}'>"
+               tpl.addn " <a href='{url.html_escape}'>"
+
+               var icon = self.icon
+               if icon != null then
+                       tpl.addn "  <span class='glyphicon glyphicon-{icon}'></span>"
+               end
+               tpl.addn " {title}"
+               tpl.addn " </a>"
+               tpl.addn "</li>"
+               return tpl
+       end
+
+       redef fun rendering do end
+end
+
+# Top menu bar template
+class DocTopMenu
+       super UnorderedList
+
+       # Brand link to display in first position of the top menu
+       #
+       # This is where you want to put your logo.
+       var brand: nullable Link is noinit, writable
+
+       # Active menu item
+       #
+       # Depends on the current page, this allows to hilighted the current item.
+       var active_item: nullable ListItem is noinit, writable
+
+       redef fun rendering do
+               addn "<nav class='navbar navbar-default navbar-fixed-top'>"
+               addn " <div class='container-fluid'>"
+               addn "  <div class='navbar-header'>"
+               add  "   <button type='button' class='navbar-toggle' "
+               addn "       data-toggle='collapse' data-target='#topmenu-collapse'>"
+               addn "    <span class='sr-only'>Toggle menu</span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "   </button>"
+               var brand = self.brand
+               if brand != null then
+                       add "<span class='navbar-brand'>"
+                       add brand
+                       add "</span>"
+               end
+               addn "  </div>"
+               addn "  <div class='collapse navbar-collapse' id='topmenu-collapse'>"
+               addn "   <ul class='nav navbar-nav'>"
+               for item in items do
+                       if item == active_item then item.css_classes.add "active"
+                       add item.write_to_string
+               end
+               addn "   </ul>"
+               addn "   <div id='search-placeholder'>"
+               addn "   </div>"
+               addn "  </div>"
+               addn " </div>"
+               addn "</nav>"
+       end
+end
+
+redef class DocSidebar
+       super Template
+
+       redef fun rendering do
+               if cards.is_empty then return
+               addn "<div id='sidebar'>"
+               for card in cards do addn card
+               addn "</div>"
+       end
+end
+
+# JS script for Piwik Tracker
+class PiwikScript
+       super Template
+
+       # Piwik URL to use for this tracker
+       var tracker_url: String
+
+       # Site ID used on Piwik system
+       var site_id: String
+
+       redef fun rendering do
+               addn "<script>"
+
+               var site_id = self.site_id.to_json
+               var tracker_url = self.tracker_url.trim
+               if tracker_url.chars.last != '/' then tracker_url += "/"
+               tracker_url = "://{tracker_url}".to_json
+
+               addn "<!-- Piwik -->"
+               addn "var _paq = _paq || [];"
+               addn " _paq.push([\"trackPageView\"]);"
+               addn " _paq.push([\"enableLinkTracking\"]);"
+               addn "(function() \{"
+               addn " var u=((\"https:\" == document.location.protocol) ? \"https\" : \"http\") + {tracker_url};"
+               addn " _paq.push([\"setTrackerUrl\", u+\"piwik.php\"]);"
+               addn " _paq.push([\"setSiteId\", {site_id}]);"
+               addn " var d=document, g=d.createElement(\"script\"), s=d.getElementsByTagName(\"script\")[0]; g.type=\"text/javascript\";"
+               addn " g.defer=true; g.async=true; g.src=u+\"piwik.js\"; s.parentNode.insertBefore(g,s);"
+               addn "\})();"
+
+               addn "</script>"
+       end
+end
+
+# Model redefs
+
+redef class MEntity
+       redef fun to_dot_node do
+               var node = super
+               node["URL"] = html_url
+               return node
+       end
+
+       redef var html_url = "{html_id}.html" is lazy
+end
+
+redef class MPackage
+       redef var html_url is lazy do return "package_{super}"
+end
+
+redef class MGroup
+       redef var html_url is lazy do return "group_{super}"
+end
+
+redef class MModule
+       redef var html_url is lazy do return "module_{super}"
+end
+
+redef class MClass
+       redef var html_url is lazy do return "class_{super}"
+end
+
+redef class MClassDef
+       redef var html_url is lazy do
+               if is_intro then return mclass.html_url
+               return "{mclass.html_url}?def=def_code_{html_id}#lin"
+       end
+end
+
+redef class MProperty
+       redef var html_url is lazy do return "property_{super}"
+end
+
+redef class MPropDef
+       redef var html_url is lazy do
+               if is_intro then return mproperty.html_url
+               return "{mproperty.html_url}?def=def_code_{html_id}#lin"
+       end
+end
+
+redef class Person
+       redef var html_url = "person_{html_id}.html" is lazy
+end
diff --git a/src/doc/static/static_index.nit b/src/doc/static/static_index.nit
new file mode 100644 (file)
index 0000000..699a480
--- /dev/null
@@ -0,0 +1,82 @@
+# 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.
+
+# Manage indexing of Nit model for Nitdoc QuickSearch.
+module static_index
+
+import static::static_html
+import json
+
+# Generate the index for then Nitdoc QuickSearch field.
+#
+# Create a JSON object containing links to:
+#  * mpackages
+#  * modules
+#  * mclasses
+#  * mpropdefs
+# All entities are grouped by name to make the research easier.
+#
+# TODO Merge with model_index
+redef class DocModel
+
+       # Build the nitdoc quick search index
+       fun create_index_file(file: String) do
+               var table = new QuickSearchTable(self)
+               var tpl = new Template
+               tpl.add "var nitdocQuickSearchRawList="
+               tpl.add table.to_json
+               tpl.add ";"
+               tpl.write_to_file(file)
+       end
+end
+
+# The result map for QuickSearch.
+private class QuickSearchTable
+       super HashMap[String, Array[QuickSearchResult]]
+
+       var doc: DocModel
+
+       init do
+               var model = doc.model
+               var filter = doc.filter
+
+               index_mentities model.collect_mpackages(filter)
+               index_mentities model.collect_mmodules(filter)
+               index_mentities model.collect_mclasses(filter)
+               index_mentities model.collect_mproperties(filter)
+       end
+
+       fun index_mentities(mentities: Collection[MEntity]) do
+               for mentity in mentities do index_mentity mentity
+       end
+
+       fun index_mentity(mentity: MEntity) do
+               var key = mentity.name
+               if not has_key(key) then
+                       self[key] = new Array[QuickSearchResult]
+               end
+               self[key].add new QuickSearchResult(mentity.full_name, mentity.html_url)
+       end
+end
+
+# A QuickSearch result.
+private class QuickSearchResult
+       serialize
+
+       # The text of the link.
+       var txt: String
+
+       # The destination of the link.
+       var url: String
+end
diff --git a/src/doc/static/static_structure.nit b/src/doc/static/static_structure.nit
new file mode 100644 (file)
index 0000000..8afe591
--- /dev/null
@@ -0,0 +1,439 @@
+# 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.
+
+# Composes the pages of the static documentation
+module static_structure
+
+import static::static_base
+
+redef class DocPage
+
+       # Create the structure of this page
+       fun apply_structure(doc: DocModel) do end
+end
+
+redef class PageHome
+       redef fun apply_structure(doc) do
+               var title = doc.custom_title or else "Welcome to Nitdoc!"
+               var intro = doc.custom_intro
+
+               if intro != null then
+                       main_tab.content.add new CardPageHeader(title)
+                       main_tab.content.add new CardText(intro)
+               else
+                       main_tab.content.add new CardPageHeader(title, "The Nit API documentation.")
+               end
+
+               main_tab.content.add new CardCatalogStats(doc.catalog)
+               main_tab.content.add new CardCatalogTags(doc.catalog)
+
+               main_tab.content.add new CardSection(2, "Packages")
+               var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
+
+               var mpackages = doc.catalog.mpackages.values.to_a
+               mpackages_sorter.sort mpackages
+               var list = new CardList("packages", "Packages")
+               for mpackage in mpackages do
+                       list.cards.add new CardCatalogPackage(doc.catalog, mpackage)
+               end
+               # TODO pagination?
+               main_tab.content.add list
+       end
+end
+
+redef class PageMEntity
+       # Concerns to display in this page.
+       var concerns: nullable ConcernsTree = null
+
+       redef fun apply_structure(doc) do
+               build_main(doc)
+               build_api(doc)
+               build_dependencies(doc)
+       end
+
+       # Build the main tab (the one that contains the MDoc)
+       fun build_main(doc: DocModel) do
+               var mentity = self.mentity
+
+               var sq = new CmdSummary(doc.model, doc.filter, mentity,
+                       markdown_processor = doc.inline_processor)
+               sq.init_command
+
+               main_tab.content.add new CardMDoc(mentity, mentity.mdoc_or_fallback)
+
+               var summary = sq.summary
+               if summary != null then
+                       main_tab.sidebar.cards.add new CardMdSummary(headlines = summary, md_processor = doc.inline_processor)
+               end
+       end
+
+       # Build the API tab
+       fun build_api(doc: DocModel) do
+               var summary = new CardSummary
+
+               var title = "All definitions"
+               if mentity isa MPackage then title = "All groups and modules"
+               if mentity isa MGroup then title = "All subgroups and modules"
+               if mentity isa MModule then title = "All class definitions"
+               if mentity isa MClass or mentity isa MClassDef then title = "All properties"
+
+               var section = new CardSection(2, title)
+               api_tab.content.add section
+               summary.cards.add section
+
+               var dq = new CmdFeatures(doc.model, doc.filter, mentity)
+               dq.init_command
+               var mentities = dq.results
+               if mentities == null then return
+
+               var list = new CardList("api", "API")
+               for m in mentities do
+                       var card = new CardMEntity(m)
+                       card.id = "api_{card.id}" # avoid id conflicts with main tab
+                       list.cards.add card
+                       summary.cards.add card
+               end
+               api_tab.content.add list
+
+               if summary.cards.not_empty then
+                       api_tab.sidebar.cards.add summary
+               end
+       end
+
+       # Build the dependencies tab
+       fun build_dependencies(doc: DocModel) do
+               var summary = new CardSummary
+
+               var model = doc.model
+               var mainmodule = doc.mainmodule
+               var filter = doc.filter
+
+               if not doc.no_dot then
+                       var gq = new CmdInheritanceGraph(model, mainmodule, filter, mentity)
+                       gq.init_command
+                       var graph = gq.graph
+                       if graph != null then
+                               graph.draw(2, 2)
+                               dep_tab.content.add new CardGraph(mentity, graph)
+                       end
+               end
+
+               # No inheritance lists for `Object`
+               if mentity isa MClass and mentity.name == "Object" then return
+
+               var inh = new HashMap[String, CmdEntityList]
+               inh["Ancestors"] = new CmdAncestors(model, mainmodule, filter, mentity, parents = false)
+               inh["Parents"] = new CmdParents(model, mainmodule, filter, mentity)
+               inh["Children"] = new CmdChildren(model, mainmodule, filter, mentity)
+               inh["Descendants"] = new CmdDescendants(model, mainmodule, filter, mentity, children = false)
+
+               for title, cmd in inh do
+                       cmd.init_command
+                       var results = cmd.results
+                       if results == null or results.is_empty then continue
+                       var section = new CardSection(3, title)
+                       dep_tab.content.add section
+                       summary.cards.add section
+
+                       var list = new CardList("inh", "Inheritance")
+                       for mentity in results do
+                               var card = new CardMEntity(mentity)
+                               list.cards.add card
+                               summary.cards.add card
+                       end
+                       dep_tab.content.add list
+               end
+
+               if summary.cards.not_empty then
+                       dep_tab.sidebar.cards.add summary
+               end
+       end
+
+       # Build the code panel
+       fun build_code(doc: DocModel) do
+               var code_url = doc.code_url
+
+               if not doc.no_code then
+                       var cq = new CmdEntityCode(doc.model, doc.modelbuilder, doc.filter, mentity)
+                       cq.init_command
+
+                       var code = cq.node
+                       if code == null then return
+                       code_tab.content.add new CardCode(mentity, code)
+               else if doc.code_url != null then
+                       code_tab = new DocTabLink("code", "Code", "console", mentity.source_url(code_url))
+               end
+       end
+
+       # Build the linearization panel
+       fun build_linearization(doc: DocModel) do
+               var summary = new CardSummary
+
+               var lq = new CmdLinearization(doc.model, doc.mainmodule, doc.filter, mentity)
+               lq.init_command
+
+               var mentities = lq.results
+               if mentities == null then return
+
+               if mentity isa MClass or mentity isa MClassDef then
+                       if mentity.name == "Object" then return # No linearization for `Object`
+                       if mentity.name == "Sys" then return # No linearization for `Sys`
+                       var section = new CardSection(2, "Class definitions")
+                       lin_tab.content.add section
+                       summary.cards.add section
+               else if mentity isa MProperty or mentity isa MPropDef then
+                       if mentity.name == "init" then return # No linearization for `init`
+                       if mentity.name == "SELF" then return # No linearization for `SELF`
+                       if mentity.name == "to_s" then return # No linearization for `to_s`
+                       var section = new CardSection(2, "Property definitions")
+                       lin_tab.content.add section
+                       summary.cards.add section
+               end
+
+               var list = new CardLinearizationList(mentity)
+               for m in mentities do
+                       var url = mentity.source_url(doc.code_url)
+                       var node = doc.modelbuilder.mentity2node(m)
+                       if node == null then continue
+                       if doc.no_code then node = null
+                       if m == mentity or
+                         (m isa MClassDef and m.is_intro) or
+                         (m isa MPropDef and m.is_intro) then
+                               var card = new CardLinearizationDef(m, node, is_active = true, url)
+                               list.cards.add card
+                               summary.cards.add card
+                       else
+                               var card = new CardLinearizationDef(m, node, is_active = false, url)
+                               list.cards.add card
+                               summary.cards.add card
+                       end
+               end
+               lin_tab.content.add list
+
+               if summary.cards.not_empty then
+                       lin_tab.sidebar.cards.add summary
+               end
+       end
+end
+
+redef class PageMPackage
+       redef fun build_main(doc) do
+               super
+               main_tab.metadata.cards.add new CardMetadata(mentity, mentity.metadata,
+                       doc.catalog.mpackages_stats[mentity],
+                       doc.catalog.deps[mentity].direct_greaters.to_a,
+                       doc.catalog.deps[mentity].direct_smallers.to_a)
+       end
+end
+
+redef class PageMModule
+       redef fun apply_structure(doc) do
+               super
+               build_code(doc)
+       end
+
+       redef fun build_main(doc) do
+               super
+
+               var summary = new CardSummary(no_title = true)
+
+               # Intros
+               var cmd: CmdEntities = new CmdIntros(doc.model, doc.mainmodule, doc.filter, mentity)
+               cmd.init_command
+               var intros = cmd.results
+               if intros != null and intros.not_empty then
+                       var section = new CardSection(3, "Introduced classes")
+                       main_tab.content.add section
+                       summary.cards.add section
+                       var cards = new CardList("intros", "Intros")
+                       for intro in intros do
+                               var card = new CardMEntity(intro)
+                               summary.cards.add card
+                               cards.cards.add card
+                       end
+                       main_tab.content.add cards
+               end
+
+               # Redefs
+               cmd = new CmdRedefs(doc.model, doc.mainmodule, doc.filter, mentity)
+               cmd.init_command
+               var redefs = cmd.results
+               if redefs != null and redefs.not_empty then
+                       var section = new CardSection(3, "Redefined classes")
+                       main_tab.content.add section
+                       summary.cards.add section
+                       var cards = new CardList("redefs", "Redefs")
+                       for prop in redefs do
+                               var card = new CardMEntity(prop)
+                               summary.cards.add card
+                               cards.cards.add card
+                       end
+                       main_tab.content.add cards
+               end
+
+               main_tab.sidebar.cards.add summary
+       end
+end
+
+redef class PageMClass
+       redef fun apply_structure(doc) do
+               super
+               build_code(doc)
+               build_linearization(doc)
+       end
+
+       redef fun build_main(doc) do
+               super
+
+               var summary = new CardSummary(no_title = true)
+
+               # Intros
+               var cmd: CmdEntities = new CmdIntros(doc.model, doc.mainmodule, doc.filter, mentity)
+               cmd.init_command
+               var intros = cmd.results
+               if intros != null and intros.not_empty then
+                       var section = new CardSection(3, "Introduced properties")
+                       main_tab.content.add section
+                       summary.cards.add section
+                       var cards = new CardList("intros", "Intros")
+                       for intro in intros do
+                               var card = new CardMEntity(intro)
+                               summary.cards.add card
+                               cards.cards.add card
+                       end
+                       main_tab.content.add cards
+               end
+
+               # Redefs
+               cmd = new CmdRedefs(doc.model, doc.mainmodule, doc.filter, mentity)
+               cmd.init_command
+               var redefs = cmd.results
+               if redefs != null and redefs.not_empty then
+                       var section = new CardSection(3, "Redefined properties")
+                       main_tab.content.add section
+                       summary.cards.add section
+                       var cards = new CardList("redefs", "Redefs")
+                       for prop in redefs do
+                               var card = new CardMEntity(prop)
+                               summary.cards.add card
+                               cards.cards.add card
+                       end
+                       main_tab.content.add cards
+               end
+
+               # Expand summary
+               main_tab.sidebar.cards.add summary
+       end
+
+       redef fun build_api(doc) do
+               var summary = new CardSummary
+
+               var section = new CardSection(2, "All properties")
+               api_tab.content.add section
+               summary.cards.add section
+
+               var dq = new CmdAllProps(doc.model, doc.mainmodule, doc.filter, mentity)
+               dq.init_command
+               var mentities = dq.results
+               if mentities == null then return
+
+               var list = new CardList("api", "API")
+               for m in mentities do
+                       var card = new CardMEntity(m)
+                       list.cards.add card
+                       summary.cards.add card
+               end
+               api_tab.content.add list
+
+               if summary.cards.not_empty then
+                       api_tab.sidebar.cards.add summary
+               end
+       end
+end
+
+redef class PageMProperty
+       redef fun apply_structure(doc) do
+               super
+               build_code(doc)
+               build_linearization(doc)
+       end
+end
+
+redef class PagePerson
+       redef fun apply_structure(doc) do
+               var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
+               main_tab.content.add new CardPageHeader(person.name, person.email)
+
+               var maint = doc.catalog.maint2proj[person]
+               mpackages_sorter.sort maint
+               var mlist = new CardList("maintained", "Maintained")
+               for mpackage in maint do
+                       mlist.cards.add new CardCatalogPackage(doc.catalog, mpackage)
+               end
+
+               # TODO pagination?
+               if maint.not_empty then
+                       main_tab.content.add new CardSection(3, "{maint.length} maintained packages")
+                       main_tab.content.add mlist
+               end
+
+               var contrib = doc.catalog.contrib2proj[person]
+               mpackages_sorter.sort contrib
+               var clist = new CardList("contribs", "Contributed")
+               for mpackage in contrib do
+                       clist.cards.add new CardCatalogPackage(doc.catalog, mpackage)
+               end
+
+               # TODO pagination?
+               if contrib.not_empty then
+                       main_tab.content.add new CardSection(3, "{contrib.length} contributed packages")
+                       main_tab.content.add clist
+               end
+       end
+end
+
+redef class PageTag
+       redef fun apply_structure(doc) do
+               var mpackages_sorter = new CatalogScoreSorter(doc.catalog)
+               main_tab.content.add new CardPageHeader(tag)
+
+               var mpackages = doc.catalog.tag2proj[tag]
+               mpackages_sorter.sort mpackages
+               var list = new CardList("packages", "Packages")
+               for mpackage in mpackages do
+                       list.cards.add new CardCatalogPackage(doc.catalog, mpackage)
+               end
+
+               # TODO pagination?
+               main_tab.content.add new CardSection(3, "{mpackages.length} packages")
+               main_tab.content.add list
+       end
+end
+
+redef class MEntity
+       # Render a HTML link for the MEntity location
+       private fun source_url(url_pattern: nullable String): String do
+               var location = self.location
+               var file = location.file
+
+               if file == null then return location.to_s
+               if url_pattern == null then return file.filename.simplify_path
+
+               var url = url_pattern
+               url = url.replace("%f", file.filename.simplify_path)
+               url = url.replace("%l", location.line_start.to_s)
+               url = url.replace("%L", location.line_end.to_s)
+               return url.simplify_path
+       end
+end
similarity index 63%
rename from src/doc/commands/commands_html.nit
rename to src/doc/templates/html_commands.nit
index 8cffb32..39e088c 100644 (file)
 # limitations under the License.
 
 # Render commands results as HTML
-module commands_html
+module html_commands
 
-import commands::commands_graph
-import commands::commands_usage
-import commands::commands_ini
-import commands::commands_main
+import commands_catalog
+import commands_docdown
+import commands_graph
+import commands_ini
+import commands_main
+import commands_parser
+import commands_usage
 
-import templates::templates_html
-import doc_down
-import highlight
+import templates::html_model
+intrude import markdown::wikilinks
 
 redef class DocCommand
 
@@ -104,6 +106,17 @@ redef class CmdComment
                end
                return tpl.write_to_string
        end
+
+       redef fun render_comment do
+               var mdoc = self.mdoc
+               if mdoc == null then return null
+
+               if format == "html" then
+                       if full_doc then return mdoc.html_documentation
+                       return mdoc.html_synopsis
+               end
+               return super
+       end
 end
 
 redef class CmdEntityLink
@@ -114,11 +127,37 @@ redef class CmdEntityLink
        end
 end
 
-redef class CmdEntityCode
+redef class CmdCode
        redef fun to_html do
-               var output = render_code(node)
-               if output == null then return ""
-               return "<pre>{output.write_to_string}</pre>"
+               var node = self.node
+               if node == null then return ""
+
+               var code = render_code(node)
+               return "<pre>{code.write_to_string}</pre>"
+       end
+
+       redef fun render_code(node) do
+               if format == "html" then
+                       var hl = new CmdHtmlightVisitor
+                       hl.show_infobox = false
+                       hl.highlight_node node
+                       return hl.html
+               end
+               return super
+       end
+end
+
+# Custom HtmlightVisitor for commands
+#
+# We create a new subclass so its behavior can be refined in clients without
+# breaking the main implementation.
+class CmdHtmlightVisitor
+       super HtmlightVisitor
+
+       redef fun hrefto(mentity) do
+               if mentity isa MClassDef then return mentity.mclass.html_url
+               if mentity isa MPropDef then return mentity.mproperty.html_url
+               return mentity.html_url
        end
 end
 
@@ -246,12 +285,6 @@ redef class CmdIniLicense
 end
 
 redef class CmdEntityFile
-
-       # URL to the file
-       #
-       # Can be refined in subtools.
-       var file_url: nullable String = file is lazy, writable
-
        redef fun to_html do
                var file = self.file
                if file == null then return ""
@@ -322,3 +355,105 @@ redef class CmdTesting
                return "<pre>{command}</pre>"
        end
 end
+
+# MDoc
+
+# Custom Markdown processor able to process doc commands
+class CmdDecorator
+       super NitdocDecorator
+
+       redef type PROCESSOR: CmdMarkdownProcessor
+
+       # Model used by wikilink commands to find entities
+       var model: Model
+
+       # Filter to apply if any
+       var filter: nullable ModelFilter
+
+       redef fun add_span_code(v, buffer, from, to) do
+               var text = new FlatBuffer
+               buffer.read(text, from, to)
+               var name = text.write_to_string
+               name = name.replace("nullable ", "")
+               var mentity = try_find_mentity(name)
+               if mentity == null then
+                       super
+               else
+                       v.add "<code>"
+                       v.emit_text mentity.html_link.write_to_string
+                       v.add "</code>"
+               end
+       end
+
+       private fun try_find_mentity(text: String): nullable MEntity do
+               var mentity = model.mentity_by_full_name(text, filter)
+               if mentity != null then return mentity
+
+               var mentities = model.mentities_by_name(text, filter)
+               if mentities.is_empty then
+                       return null
+               else if mentities.length > 1 then
+                       # TODO smart resolve conflicts
+               end
+               return mentities.first
+       end
+
+       redef fun add_wikilink(v, token) do
+               v.render_wikilink(token, model)
+       end
+end
+
+# Same as `InlineDecorator` but with wikilink commands handling
+class CmdInlineDecorator
+       super InlineDecorator
+
+       redef type PROCESSOR: CmdMarkdownProcessor
+
+       # Model used by wikilink commands to find entities
+       var model: Model
+
+       redef fun add_wikilink(v, token) do
+               v.render_wikilink(token, model)
+       end
+end
+
+# Custom MarkdownEmitter for commands
+class CmdMarkdownProcessor
+       super MarkdownProcessor
+
+       # Parser used to process doc commands
+       var parser: CommandParser
+
+       # Render a wikilink
+       fun render_wikilink(token: TokenWikiLink, model: Model) do
+               var link = token.link
+               if link == null then return
+               var name = token.name
+               if name != null then link = "{name} | {link}"
+
+               var command = parser.parse(link.write_to_string)
+               var error = parser.error
+
+               if error isa CmdError then
+                       emit_text error.to_html.write_to_string
+                       return
+               end
+               if error isa CmdWarning then
+                       emit_text error.to_html.write_to_string
+               end
+               add command.as(not null).to_html
+       end
+end
+
+redef class Text
+       # Read `self` between `nstart` and `nend` (excluded) and writte chars to `out`.
+       private fun read(out: FlatBuffer, nstart, nend: Int): Int do
+               var pos = nstart
+               while pos < length and pos < nend do
+                       out.add self[pos]
+                       pos += 1
+               end
+               if pos == length then return -1
+               return pos
+       end
+end
similarity index 59%
rename from src/doc/templates/templates_html.nit
rename to src/doc/templates/html_model.nit
index f74ac84..6ec000f 100644 (file)
 # limitations under the License.
 
 # Translate mentities to html blocks.
-module templates_html
+module html_model
 
 import model::model_collect
-import doc::doc_down
+import catalog
+
+import markdown
+import htmlight
 import html::bootstrap
+private import parser_util
 
 redef class MEntity
 
@@ -46,7 +50,7 @@ redef class MEntity
                end
                var mdoc = self.mdoc_or_fallback
                if title == null and mdoc != null then
-                       title = mdoc.synopsis.html_escape
+                       title = mdoc.synopsis
                end
                return new Link(html_url, text, title)
        end
@@ -85,18 +89,6 @@ redef class MEntity
        # An icon representative of the mentity
        fun html_icon: BSIcon do return new BSIcon("tag", ["text-muted"])
 
-       # A li element that can go in a `HTMLList`
-       fun html_list_item: ListItem do
-               var tpl = new Template
-               tpl.add html_namespace
-               var comment = mdoc_or_fallback
-               if comment != null then
-                       tpl.add ": "
-                       tpl.add comment.html_synopsis
-               end
-               return new ListItem(tpl)
-       end
-
        # CSS classes used to decorate `self`
        #
        # Mainly used for icons.
@@ -263,7 +255,9 @@ redef class MMethodDef
                if mproperty.is_root_init and new_msignature != null then
                        return new_msignature.html_signature(short)
                end
-               return msignature.as(not null).html_signature(short)
+               var msignature = self.msignature
+               if msignature == null then return new Template
+               return msignature.html_signature(short)
        end
 end
 
@@ -360,3 +354,221 @@ redef class MParameter
                return tpl
        end
 end
+
+# Catalog
+
+redef class Person
+
+       # HTML uniq id
+       fun html_id: String do return name.to_cmangle
+
+       # HTML default URL
+       #
+       # Should be redefined in clients.
+       fun html_url: String do return "person_{html_id}.html"
+
+       # Link to this person `html_url`
+       fun html_link: Link do return new Link(html_url, name)
+
+       # Render `self` as HTML
+       fun to_html: String do
+               var tpl = new Template
+               tpl.addn "<span>"
+               var gravatar = self.gravatar
+               if gravatar != null then
+                       tpl.addn "<img class='avatar' src='https://secure.gravatar.com/avatar/{gravatar}?size=14&amp;default=retro' />"
+               end
+               tpl.addn html_link
+               tpl.addn "</span>"
+               return tpl.write_to_string
+       end
+end
+
+# MDoc
+
+redef class MDoc
+
+       private var markdown_proc: MarkdownProcessor is lazy, writable do
+               return original_mentity.as(not null).model.nitdoc_md_processor
+       end
+
+       private var inline_proc: MarkdownProcessor is lazy, writable do
+               return original_mentity.as(not null).model.nitdoc_inline_processor
+       end
+
+       # Renders the synopsis as a HTML comment block.
+       var html_synopsis: Writable is lazy do
+               var res = new Template
+               var syn = inline_proc.process(content.first)
+               res.add "<span class=\"synopsys nitdoc\">{syn}</span>"
+               return res
+       end
+
+       # Renders the comment without the synopsis as a HTML comment block.
+       var html_comment: Writable is lazy do
+               var lines = content.to_a
+               if not lines.is_empty then lines.shift
+               return lines_to_html(lines)
+       end
+
+       # Renders the synopsis and the comment as a HTML comment block.
+       var html_documentation: Writable is lazy do return lines_to_html(content.to_a)
+
+       # Renders markdown line as a HTML comment block.
+       private fun lines_to_html(lines: Array[String]): Writable do
+               var res = new Template
+               var decorator = markdown_proc.decorator.as(NitdocDecorator)
+               decorator.current_mdoc = self
+               res.add "<div class=\"nitdoc\">"
+               # do not use DocUnit as synopsys
+               if not lines.is_empty then
+                       if not lines.first.has_prefix("    ") and
+                          not lines.first.has_prefix("\t") then
+                               # parse synopsys
+                               var syn = inline_proc.process(lines.shift)
+                               res.add "<h1 class=\"synopsys\">{syn}</h1>"
+                       end
+               end
+               # check for annotations
+               for i in [0 .. lines.length[ do
+                       var line = lines[i]
+                       if line.to_upper.has_prefix("ENSURE") or line.to_upper.has_prefix("REQUIRE") then
+                               var html = inline_proc.process(line)
+                               lines[i] = "<p class=\"contract\">{html}</p>"
+                       else if line.to_upper.has_prefix("TODO") or line.to_upper.has_prefix("FIXME") then
+                               var html = inline_proc.process(line)
+                               lines[i] = "<p class=\"todo\">{html}</p>"
+                       end
+               end
+               # add other lines
+               res.add markdown_proc.process(lines.join("\n"))
+               res.add "</div>"
+               decorator.current_mdoc = null
+               return res
+       end
+end
+
+# The specific markdown decorator used internally to process MDoc object.
+#
+# You should use the various methods of `MDoc` like `MDoc::html_documentation`
+#
+# The class is public so specific behavior can be plugged on it.
+class NitdocDecorator
+       super HTMLDecorator
+
+       private var toolcontext = new ToolContext
+
+       # The currently processed mdoc.
+       #
+       # Unfortunately, this seems to be the simpler way to get the currently processed `MDoc` object.
+       var current_mdoc: nullable MDoc = null
+
+       redef fun add_code(v, block) do
+               var meta = block.meta or else "nit"
+
+               # Do not try to highlight non-nit code.
+               if meta != "nit" and meta != "nitish" then
+                       v.add "<pre class=\"{meta}\"><code>"
+                       v.emit_in block
+                       v.add "</code></pre>\n"
+                       return
+               end
+               # Try to parse code
+               var code = block.raw_content
+               var ast = toolcontext.parse_something(code)
+               if ast isa AError then
+                       v.add "<pre class=\"{meta}\"><code>"
+                       v.emit_in block
+                       v.add "</code></pre>\n"
+                       return
+               end
+               v.add "<pre class=\"nitcode\"><code>"
+               var hl = new HtmlightVisitor
+               hl.line_id_prefix = ""
+               hl.highlight_node(ast)
+               v.add(hl.html)
+               v.add "</code></pre>\n"
+       end
+
+       redef fun add_span_code(v, text, from, to) do
+               # Try to parse it
+               var code = code_from_text(text, from, to)
+               var ast = toolcontext.parse_something(code)
+
+               if ast isa AError then
+                       v.add "<code class=\"rawcode\">"
+                       append_code(v, text, from, to)
+               else
+                       v.add "<code class=\"nitcode\">"
+                       var hl = new HtmlightVisitor
+                       hl.line_id_prefix = ""
+                       hl.highlight_node(ast)
+                       v.add(hl.html)
+               end
+               v.add "</code>"
+       end
+
+       private fun code_from_text(buffer: Text, from, to: Int): String do
+               var out = new FlatBuffer
+               for i in [from..to[ do out.add buffer[i]
+               return out.write_to_string
+       end
+end
+
+# Decorator for span elements.
+#
+# Because inline comments can appear as span elements,
+# InlineDecorator do not decorate things like paragraphs or headers.
+class InlineDecorator
+       super NitdocDecorator
+
+       redef fun add_paragraph(v, block) do
+               v.emit_in block
+       end
+
+       redef fun add_headline(v, block) do
+               # save headline
+               var line = block.block.first_line
+               if line == null then return
+               var txt = line.value
+               var id = strip_id(txt)
+               var lvl = block.depth
+               headlines[id] = new HeadLine(id, txt, lvl)
+
+               v.emit_in block
+       end
+
+       redef fun add_code(v, block) do
+               # Try to parse code
+               var ast = toolcontext.parse_something(block.block.text.to_s)
+               if ast isa AError then
+                       v.add "<code>"
+                       v.emit_in block
+                       v.add "</code>"
+                       return
+               end
+               v.add "<code class=\"nitcode\">"
+               var hl = new HtmlightVisitor
+               hl.highlight_node(ast)
+               v.add(hl.html)
+               v.add "</code>"
+       end
+end
+
+redef class Model
+       # Get a markdown processor for Nitdoc comments.
+       var nitdoc_md_processor: MarkdownProcessor is lazy, writable do
+               var proc = new MarkdownProcessor
+               proc.decorator = new NitdocDecorator
+               return proc
+       end
+
+       # Get a markdown inline processor for Nitdoc comments.
+       #
+       # This processor is specificaly designed to inlinable doc elements like synopsys.
+       var nitdoc_inline_processor: MarkdownProcessor is lazy, writable do
+               var proc = new MarkdownProcessor
+               proc.decorator = new InlineDecorator
+               return proc
+       end
+end
similarity index 91%
rename from src/doc/commands/commands_json.nit
rename to src/doc/templates/json_commands.nit
index b109c87..aea7be3 100644 (file)
 # limitations under the License.
 
 # Translate command results to json
-module commands_json
+module json_commands
 
-import commands::commands_model
-import commands::commands_graph
-import commands::commands_usage
-import commands::commands_catalog
-import commands::commands_ini
-import commands::commands_main
+import commands_catalog
+import commands_graph
+import commands_ini
+import commands_main
+import commands_usage
 
-import templates::templates_json
-import catalog::catalog_json
+import templates::json_model
+import json::static
 
 redef class DocCommand
        # Return a JSON Serializable representation of `self` results
@@ -86,17 +85,15 @@ redef class CmdEntityLink
        end
 end
 
-redef class CmdEntityCode
+redef class CmdCode
        redef fun to_json do
                var obj = new JsonObject
                var node = self.node
-               if node != null then
-                       obj["location"] = node.location
-               end
-               var output = render_code(node)
-               if output != null then
-                       obj["code"] = output.write_to_string
-               end
+               if node == null then return obj
+
+               var code = render_code(node)
+               obj["location"] = node.location
+               obj["code"] = code.write_to_string
                return obj
        end
 end
similarity index 82%
rename from src/doc/templates/templates_json.nit
rename to src/doc/templates/json_model.nit
index a75dc49..b91a237 100644 (file)
 # rather than the refs.
 #
 # TODO consider serialization module?
-module templates_json
+module json_model
 
 import model::model_collect
-import json::static
 import json::serialization_write
 import catalog
-import doc_down
+
+import html_model
 
 redef class MEntity
        serialize
@@ -376,3 +376,72 @@ end
 redef class String
        super JsonRef
 end
+
+# Catalog
+
+redef class MPackageMetadata
+       serialize
+
+       redef fun core_serialize_to(v) do
+               super
+               v.serialize_attribute("license", license)
+               v.serialize_attribute("maintainers", maintainers)
+               v.serialize_attribute("contributors", contributors)
+               v.serialize_attribute("tags", tags)
+               v.serialize_attribute("tryit", tryit)
+               v.serialize_attribute("apk", apk)
+               v.serialize_attribute("homepage", homepage)
+               v.serialize_attribute("browse", browse)
+               v.serialize_attribute("git", git)
+               v.serialize_attribute("issues", issues)
+               v.serialize_attribute("first_date", first_date)
+               v.serialize_attribute("last_date", last_date)
+       end
+end
+
+# Catalog statistics
+redef class CatalogStats
+       serialize
+
+       redef fun core_serialize_to(v) do
+               super
+               v.serialize_attribute("packages", packages)
+               v.serialize_attribute("maintainers", maintainers)
+               v.serialize_attribute("contributors", contributors)
+               v.serialize_attribute("tags", tags)
+               v.serialize_attribute("modules", modules)
+               v.serialize_attribute("classes", classes)
+               v.serialize_attribute("methods", methods)
+               v.serialize_attribute("loc", loc)
+       end
+end
+
+# MPackage statistics for the catalog
+redef class MPackageStats
+       serialize
+
+       redef fun core_serialize_to(v) do
+               super
+               v.serialize_attribute("mmodules", mmodules)
+               v.serialize_attribute("mclasses", mclasses)
+               v.serialize_attribute("mmethods", mmethods)
+               v.serialize_attribute("loc", loc)
+               v.serialize_attribute("errors", errors)
+               v.serialize_attribute("warnings", warnings)
+               v.serialize_attribute("warnings_per_kloc", warnings_per_kloc)
+               v.serialize_attribute("documentation_score", documentation_score)
+               v.serialize_attribute("commits", commits)
+               v.serialize_attribute("score", score)
+       end
+end
+
+redef class Person
+       serialize
+
+       redef fun core_serialize_to(v) do
+               super
+               v.serialize_attribute("name", name)
+               v.serialize_attribute("email", email)
+               v.serialize_attribute("gravatar", gravatar)
+       end
+end
similarity index 79%
rename from src/doc/commands/commands_md.nit
rename to src/doc/templates/md_commands.nit
index 77ad14a..4c004c7 100644 (file)
 # limitations under the License.
 
 # Render commands results as Markdown
-module commands_md
+module md_commands
 
-import commands::commands_graph
-import commands::commands_usage
-import commands::commands_ini
-import commands::commands_main
+import commands_catalog
+import commands_graph
+import commands_ini
+import commands_main
+import commands_usage
 
-import doc_down
+import highlight
 
 redef class DocCommand
 
@@ -89,6 +90,17 @@ redef class CmdComment
                end
                return tpl.write_to_string
        end
+
+       redef fun render_comment do
+               var mdoc = self.mdoc
+               if mdoc == null then return null
+
+               if format == "md" then
+                       if full_doc then return mdoc.md_documentation
+                       return mdoc.md_synopsis
+               end
+               return super
+       end
 end
 
 redef class CmdEntityLink
@@ -99,17 +111,27 @@ redef class CmdEntityLink
        end
 end
 
-redef class CmdEntityCode
+redef class CmdCode
        redef fun to_md do
-               var output = render_code(node)
-               if output == null then return ""
+               var node = self.node
+               if node == null then return ""
 
+               var code = render_code(node)
                var tpl = new Template
                tpl.addn "~~~nit"
-               tpl.add output.write_to_string
+               tpl.add code.write_to_string
                tpl.addn "~~~"
                return tpl.write_to_string
        end
+
+       redef fun render_code(node) do
+               if format == "ansi" then
+                       var hl = new AnsiHighlightVisitor
+                       hl.highlight_node node
+                       return hl.result
+               end
+               return super
+       end
 end
 
 redef class CmdAncestors
@@ -320,3 +342,39 @@ redef class CmdTesting
                return tpl.write_to_string
        end
 end
+
+# MDoc
+
+redef class MDoc
+
+       # Renders the synopsis as a HTML comment block.
+       var md_synopsis: Writable is lazy do
+               if content.is_empty then return ""
+               return content.first
+       end
+
+       #
+       var md_comment: Writable is lazy do
+               if content.is_empty then return ""
+               var lines = content.to_a
+               lines.shift
+               return lines.join("\n")
+       end
+
+       # Renders the synopsis and the comment as a HTML comment block.
+       var md_documentation: Writable is lazy do return lines_to_md(content.to_a)
+
+       private fun lines_to_md(lines: Array[String]): Writable do
+               var res = new Template
+               if not lines.is_empty then
+                       var syn = lines.first
+                       if not syn.has_prefix("    ") and not syn.has_prefix("\t") and
+                         not syn.trim.has_prefix("#") then
+                               lines.shift
+                               res.add "# {syn}\n"
+                       end
+               end
+               res.add lines.join("\n")
+               return res
+       end
+end
similarity index 99%
rename from src/doc/templates/templates_term.nit
rename to src/doc/templates/term_model.nit
index b4fc2fe..4a442c5 100644 (file)
@@ -16,7 +16,7 @@
 #
 # This module introduces Markdown rendering services in model entities.
 # With the `no_color` option set to `false`, the output can be highlighted for console.
-module templates_term
+module term_model
 
 import model_collect
 import console
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module test_commands_html is test
+module test_html_commands is test
 
 import test_commands
 intrude import doc::commands::commands_main
-import doc::commands::commands_html
+import html_commands
 
 class TestCommandsHtml
        super TestCommands
@@ -30,19 +30,19 @@ class TestCommandsHtml
        # CmdEntity
 
        fun test_cmd_entity is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntity(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_comment is test do
-               var cmd = new CmdComment(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdComment(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_link is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -50,25 +50,25 @@ class TestCommandsHtml
        # CmdInheritance
 
        fun test_cmd_parents is test do
-               var cmd = new CmdParents(test_view, mentity_name = "test_prog::Warrior")
+               var cmd = new CmdParents(test_model, test_main, mentity_name = "test_prog::Warrior")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ancestors is test do
-               var cmd = new CmdAncestors(test_view, mentity_name = "test_prog::Warrior", parents = false)
+               var cmd = new CmdAncestors(test_model, test_main, mentity_name = "test_prog::Warrior", parents = false)
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_children is test do
-               var cmd = new CmdChildren(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdChildren(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_descendants is test do
-               var cmd = new CmdDescendants(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdDescendants(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -76,7 +76,7 @@ class TestCommandsHtml
        # CmdSearch
 
        fun test_cmd_search is test do
-               var cmd = new CmdSearch(test_view, query = "Carer", limit = 10)
+               var cmd = new CmdSearch(test_model, query = "Carer", limit = 10)
                cmd.init_command
                print_html cmd.to_html
        end
@@ -84,7 +84,7 @@ class TestCommandsHtml
        # CmdFeatures
 
        fun test_cmd_features is test do
-               var cmd = new CmdFeatures(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdFeatures(test_model, mentity_name = "test_prog::Career")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -92,7 +92,7 @@ class TestCommandsHtml
        # CmdLinearization
 
        fun test_cmd_lin is test do
-               var cmd = new CmdLinearization(test_view, mentity_name = "init")
+               var cmd = new CmdLinearization(test_model, test_main, mentity_name = "init")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -100,7 +100,7 @@ class TestCommandsHtml
        # CmdModel
 
        fun test_cmd_mentities is test do
-               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var cmd = new CmdModelEntities(test_model, kind = "modules")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -108,25 +108,25 @@ class TestCommandsHtml
        # CmdUsage
 
        fun test_cmd_new is test do
-               var cmd = new CmdNew(test_view, test_builder, mentity_name = "test_prog::Character")
+               var cmd = new CmdNew(test_model, test_builder, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_call is test do
-               var cmd = new CmdCall(test_view, test_builder, mentity_name = "strength_bonus")
+               var cmd = new CmdCall(test_model, test_builder, mentity_name = "strength_bonus")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_return is test do
-               var cmd = new CmdReturn(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdReturn(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_param is test do
-               var cmd = new CmdParam(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdParam(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_html cmd.to_html
        end
@@ -134,70 +134,70 @@ class TestCommandsHtml
        # CmdIni
 
        fun test_cmd_ini_desc is test do
-               var cmd = new CmdIniDescription(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniDescription(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_git is test do
-               var cmd = new CmdIniGitUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniGitUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_clone is test do
-               var cmd = new CmdIniCloneCommand(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniCloneCommand(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_issues is test do
-               var cmd = new CmdIniIssuesUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniIssuesUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_maintainer is test do
-               var cmd = new CmdIniMaintainer(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniMaintainer(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_contributors is test do
-               var cmd = new CmdIniContributors(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniContributors(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_license is test do
-               var cmd = new CmdIniLicense(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniLicense(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_license_file is test do
-               var cmd = new CmdLicenseFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_license_file_content is test do
-               var cmd = new CmdLicenseFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_contrib_file is test do
-               var cmd = new CmdContribFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_html cmd.to_html
        end
 
        fun test_cmd_ini_contrib_file_content is test do
-               var cmd = new CmdContribFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_html cmd.to_html
@@ -206,31 +206,31 @@ class TestCommandsHtml
        # CmdMain
 
        fun test_cmd_mains is test do
-               var cmd = new CmdMains(test_view, mentity_name = "test_prog")
+               var cmd = new CmdMains(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_main_compile is test do
-               var cmd = new CmdMainCompile(test_view, mentity_name = "test_prog::test_prog")
+               var cmd = new CmdMainCompile(test_model, mentity_name = "test_prog::test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_testing is test do
-               var cmd = new CmdTesting(test_view, mentity_name = "test_prog")
+               var cmd = new CmdTesting(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_man_synopsis is test do
-               var cmd = new CmdManSynopsis(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManSynopsis(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
 
        fun test_cmd_man_options is test do
-               var cmd = new CmdManOptions(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManOptions(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_html cmd.to_html
        end
diff --git a/src/doc/templates/tests/test_html_commands.sav/test_cmd_search.res b/src/doc/templates/tests/test_html_commands.sav/test_cmd_search.res
new file mode 100644 (file)
index 0000000..2953e58
--- /dev/null
@@ -0,0 +1 @@
+<ul><li><a href="test_prog_58d_58dCareer" title="A `Career` gives a characteristic bonus or malus to the character.">Career</a> - <span class="synopsys nitdoc">A <code class="nitcode"><span class="nitcode"><span class="line"><span class="nc_t">Career</span></span></span></code> gives a characteristic bonus or malus to the character.</span></li></ul>
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module test_commands_json is test
+module test_json_commands is test
 
 import test_commands
 intrude import doc::commands::commands_main
-import doc::commands::commands_json
+import json_commands
 
 class TestCommandsJson
        super TestCommands
@@ -30,19 +30,19 @@ class TestCommandsJson
        # CmdEntity
 
        fun test_cmd_entity is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntity(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_comment is test do
-               var cmd = new CmdComment(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdComment(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_link is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -50,25 +50,25 @@ class TestCommandsJson
        # CmdInheritance
 
        fun test_cmd_parents is test do
-               var cmd = new CmdParents(test_view, mentity_name = "test_prog::Warrior")
+               var cmd = new CmdParents(test_model, test_main, mentity_name = "test_prog::Warrior")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ancestors is test do
-               var cmd = new CmdAncestors(test_view, mentity_name = "test_prog::Warrior", parents = false)
+               var cmd = new CmdAncestors(test_model, test_main, mentity_name = "test_prog::Warrior", parents = false)
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_children is test do
-               var cmd = new CmdChildren(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdChildren(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_descendants is test do
-               var cmd = new CmdDescendants(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdDescendants(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -76,7 +76,7 @@ class TestCommandsJson
        # CmdSearch
 
        fun test_cmd_search is test do
-               var cmd = new CmdSearch(test_view, query = "Carer", limit = 10)
+               var cmd = new CmdSearch(test_model, query = "Carer", limit = 10)
                cmd.init_command
                print_json cmd.to_json
        end
@@ -84,7 +84,7 @@ class TestCommandsJson
        # CmdFeatures
 
        fun test_cmd_features is test do
-               var cmd = new CmdFeatures(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdFeatures(test_model, mentity_name = "test_prog::Career")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -92,7 +92,7 @@ class TestCommandsJson
        # CmdLinearization
 
        fun test_cmd_lin is test do
-               var cmd = new CmdLinearization(test_view, mentity_name = "init")
+               var cmd = new CmdLinearization(test_model, test_main, mentity_name = "init")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -100,7 +100,7 @@ class TestCommandsJson
        # CmdModel
 
        fun test_cmd_mentities is test do
-               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var cmd = new CmdModelEntities(test_model, kind = "modules")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -108,25 +108,25 @@ class TestCommandsJson
        # CmdUsage
 
        fun test_cmd_new is test do
-               var cmd = new CmdNew(test_view, test_builder, mentity_name = "test_prog::Character")
+               var cmd = new CmdNew(test_model, test_builder, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_call is test do
-               var cmd = new CmdCall(test_view, test_builder, mentity_name = "strength_bonus")
+               var cmd = new CmdCall(test_model, test_builder, mentity_name = "strength_bonus")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_return is test do
-               var cmd = new CmdReturn(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdReturn(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_param is test do
-               var cmd = new CmdParam(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdParam(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_json cmd.to_json
        end
@@ -134,70 +134,70 @@ class TestCommandsJson
        # CmdIni
 
        fun test_cmd_ini_desc is test do
-               var cmd = new CmdIniDescription(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniDescription(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_git is test do
-               var cmd = new CmdIniGitUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniGitUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_clone is test do
-               var cmd = new CmdIniCloneCommand(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniCloneCommand(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_issues is test do
-               var cmd = new CmdIniIssuesUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniIssuesUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_maintainer is test do
-               var cmd = new CmdIniMaintainer(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniMaintainer(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_contributors is test do
-               var cmd = new CmdIniContributors(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniContributors(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_license is test do
-               var cmd = new CmdIniLicense(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniLicense(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_license_file is test do
-               var cmd = new CmdLicenseFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_license_file_content is test do
-               var cmd = new CmdLicenseFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_contrib_file is test do
-               var cmd = new CmdContribFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_json cmd.to_json
        end
 
        fun test_cmd_ini_contrib_file_content is test do
-               var cmd = new CmdContribFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_json cmd.to_json
@@ -206,31 +206,31 @@ class TestCommandsJson
        # CmdMain
 
        fun test_cmd_mains is test do
-               var cmd = new CmdMains(test_view, mentity_name = "test_prog")
+               var cmd = new CmdMains(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_main_compile is test do
-               var cmd = new CmdMainCompile(test_view, mentity_name = "test_prog::test_prog")
+               var cmd = new CmdMainCompile(test_model, mentity_name = "test_prog::test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_testing is test do
-               var cmd = new CmdTesting(test_view, mentity_name = "test_prog")
+               var cmd = new CmdTesting(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_man_synopsis is test do
-               var cmd = new CmdManSynopsis(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManSynopsis(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
 
        fun test_cmd_man_options is test do
-               var cmd = new CmdManOptions(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManOptions(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_json cmd.to_json
        end
diff --git a/src/doc/templates/tests/test_json_commands.sav/test_cmd_search.res b/src/doc/templates/tests/test_json_commands.sav/test_cmd_search.res
new file mode 100644 (file)
index 0000000..93e7114
--- /dev/null
@@ -0,0 +1,22 @@
+{
+       "results": [{
+               "name": "Career",
+               "synopsis": "A `Career` gives a characteristic bonus or malus to the character.",
+               "namespace": [{
+                       "name": "test_prog",
+                       "synopsis": "Test program for model tools."
+               }, "::", {
+                       "name": "Career",
+                       "synopsis": "A `Career` gives a characteristic bonus or malus to the character."
+               }],
+               "class_name": "MClass",
+               "full_name": "test_prog::Career",
+               "visibility": "public",
+               "html_synopsis": "<span class=\"synopsys nitdoc\">A <code class=\"nitcode\"><span class=\"nitcode\"><span class=\"line\"><span class=\"nc_t\">Career</span></span></span></code> gives a characteristic bonus or malus to the character.</span>",
+               "modifiers": ["abstract class"]
+       }],
+       "page": 1,
+       "count": 1,
+       "limit": 10,
+       "max": 1
+}
@@ -12,9 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module test_templates_json is test
+module test_json_model is test
 
-import templates_json
+import json_model
 import frontend
 
 class TestModelSerialization
similarity index 63%
rename from src/doc/commands/tests/test_commands_md.nit
rename to src/doc/templates/tests/test_md_commands.nit
index 941c3b2..de7d655 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module test_commands_md is test
+module test_md_commands is test
 
 import test_commands
 intrude import doc::commands::commands_main
-import doc::commands::commands_md
+import md_commands
 
 class TestCommandsMd
        super TestCommands
@@ -30,19 +30,19 @@ class TestCommandsMd
        # CmdEntity
 
        fun test_cmd_entity is test do
-               var cmd = new CmdEntity(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntity(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_comment is test do
-               var cmd = new CmdComment(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdComment(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_link is test do
-               var cmd = new CmdEntityLink(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdEntityLink(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -50,25 +50,25 @@ class TestCommandsMd
        # CmdInheritance
 
        fun test_cmd_parents is test do
-               var cmd = new CmdParents(test_view, mentity_name = "test_prog::Warrior")
+               var cmd = new CmdParents(test_model, test_main, mentity_name = "test_prog::Warrior")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ancestors is test do
-               var cmd = new CmdAncestors(test_view, mentity_name = "test_prog::Warrior", parents = false)
+               var cmd = new CmdAncestors(test_model, test_main, mentity_name = "test_prog::Warrior", parents = false)
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_children is test do
-               var cmd = new CmdChildren(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdChildren(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_descendants is test do
-               var cmd = new CmdDescendants(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdDescendants(test_model, test_main, mentity_name = "test_prog::Career")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -76,7 +76,7 @@ class TestCommandsMd
        # CmdSearch
 
        fun test_cmd_search is test do
-               var cmd = new CmdSearch(test_view, query = "Carer", limit = 10)
+               var cmd = new CmdSearch(test_model, query = "Carer", limit = 10)
                cmd.init_command
                print_md cmd.to_md
        end
@@ -84,7 +84,7 @@ class TestCommandsMd
        # CmdFeatures
 
        fun test_cmd_features is test do
-               var cmd = new CmdFeatures(test_view, mentity_name = "test_prog::Career")
+               var cmd = new CmdFeatures(test_model, mentity_name = "test_prog::Career")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -92,7 +92,7 @@ class TestCommandsMd
        # CmdLinearization
 
        fun test_cmd_lin is test do
-               var cmd = new CmdLinearization(test_view, mentity_name = "init")
+               var cmd = new CmdLinearization(test_model, test_main, mentity_name = "init")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -100,7 +100,7 @@ class TestCommandsMd
        # CmdModel
 
        fun test_cmd_mentities is test do
-               var cmd = new CmdModelEntities(test_view, kind = "modules")
+               var cmd = new CmdModelEntities(test_model, kind = "modules")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -108,25 +108,25 @@ class TestCommandsMd
        # CmdUsage
 
        fun test_cmd_new is test do
-               var cmd = new CmdNew(test_view, test_builder, mentity_name = "test_prog::Character")
+               var cmd = new CmdNew(test_model, test_builder, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_call is test do
-               var cmd = new CmdCall(test_view, test_builder, mentity_name = "strength_bonus")
+               var cmd = new CmdCall(test_model, test_builder, mentity_name = "strength_bonus")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_return is test do
-               var cmd = new CmdReturn(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdReturn(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_param is test do
-               var cmd = new CmdParam(test_view, mentity_name = "test_prog::Character")
+               var cmd = new CmdParam(test_model, mentity_name = "test_prog::Character")
                cmd.init_command
                print_md cmd.to_md
        end
@@ -134,70 +134,70 @@ class TestCommandsMd
        # CmdIni
 
        fun test_cmd_ini_desc is test do
-               var cmd = new CmdIniDescription(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniDescription(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_git is test do
-               var cmd = new CmdIniGitUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniGitUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_clone is test do
-               var cmd = new CmdIniCloneCommand(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniCloneCommand(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_issues is test do
-               var cmd = new CmdIniIssuesUrl(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniIssuesUrl(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_maintainer is test do
-               var cmd = new CmdIniMaintainer(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniMaintainer(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_contributors is test do
-               var cmd = new CmdIniContributors(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniContributors(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_license is test do
-               var cmd = new CmdIniLicense(test_view, mentity_name = "test_prog")
+               var cmd = new CmdIniLicense(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_license_file is test do
-               var cmd = new CmdLicenseFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_license_file_content is test do
-               var cmd = new CmdLicenseFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdLicenseFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_contrib_file is test do
-               var cmd = new CmdContribFile(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFile(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_md cmd.to_md
        end
 
        fun test_cmd_ini_contrib_file_content is test do
-               var cmd = new CmdContribFileContent(test_view, mentity_name = "test_prog")
+               var cmd = new CmdContribFileContent(test_model, mentity_name = "test_prog")
                cmd.init_command
                cmd.file = cmd.file.as(not null).basename # for testing path
                print_md cmd.to_md
@@ -206,31 +206,31 @@ class TestCommandsMd
        # CmdMain
 
        fun test_cmd_mains is test do
-               var cmd = new CmdMains(test_view, mentity_name = "test_prog")
+               var cmd = new CmdMains(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_main_compile is test do
-               var cmd = new CmdMainCompile(test_view, mentity_name = "test_prog::test_prog")
+               var cmd = new CmdMainCompile(test_model, mentity_name = "test_prog::test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_testing is test do
-               var cmd = new CmdTesting(test_view, mentity_name = "test_prog")
+               var cmd = new CmdTesting(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_man_synopsis is test do
-               var cmd = new CmdManSynopsis(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManSynopsis(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
 
        fun test_cmd_man_options is test do
-               var cmd = new CmdManOptions(test_view, mentity_name = "test_prog")
+               var cmd = new CmdManOptions(test_model, mentity_name = "test_prog")
                cmd.init_command
                print_md cmd.to_md
        end
diff --git a/src/doc/templates/tests/test_md_commands.sav/test_cmd_search.res b/src/doc/templates/tests/test_md_commands.sav/test_cmd_search.res
new file mode 100644 (file)
index 0000000..695c2ff
--- /dev/null
@@ -0,0 +1 @@
+* `Career` - A `Career` gives a characteristic bonus or malus to the character.
index 58ad127..7d490e4 100644 (file)
@@ -15,7 +15,8 @@
 module term
 
 import commands::commands_parser
-import templates::templates_term
+import templates::term_model
+import templates::md_commands
 
 redef class CommandParser
 
@@ -25,8 +26,8 @@ redef class CommandParser
 
                # Translate links to doc commands
                if cmd isa CmdEntityLink then
-                       cmd = new CmdComment(view, mentity_name = query)
-                       var opts = new HashMap[String, String]
+                       cmd = new CmdComment(model, mentity_name = query)
+                       var opts = new CmdOptions
                        var status = cmd.parser_init(query, opts)
                        if not status isa CmdSuccess then error = status
                end
@@ -221,13 +222,12 @@ redef class CmdEntityCode
                else
                        print title
                end
-               if no_color == null or not no_color then
+               var node = self.node
+               if (no_color == null or not no_color) and node != null then
                        var ansi = render_code(node)
-                       if ansi != null then
-                               print "~~~"
-                               print ansi.write_to_string
-                               print "~~~"
-                       end
+                       print "~~~"
+                       print ansi.write_to_string
+                       print "~~~"
                else
                        printn mentity.cs_source_code
                end
index 997037c..1b507fe 100644 (file)
@@ -26,237 +26,237 @@ class TestTerm
        # CmdEntity
 
        fun test_mentity_full_name is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("test_prog::Character", true)
        end
 
        fun test_mentity_name is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("Character", true)
        end
 
        fun test_mentity_empty is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("", true)
        end
 
        fun test_mentity_not_found is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("Caracter", true)
        end
 
        fun test_mentity_conflict is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("+", true)
        end
 
        # CmdDoc
 
        fun test_comment is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("doc: Character", true)
        end
 
        fun test_comment_short is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("doc: Character | only-synopsis", true)
        end
 
        fun test_comment_no_fallback is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("doc: Character | no-fallback", true)
        end
 
        # CmdInheritance
 
        fun test_ancestors is test do
-               var parser = new CommandParser(test_view, test_builder)
-               parser.execute("ancestors: Warrior | parents: true", true)
+               var parser = new CommandParser(test_model, test_main, test_builder)
+               parser.execute("ancestors: Warrior | no-parents: false", true)
        end
 
        fun test_ancestors_without_parents is test do
-               var parser = new CommandParser(test_view, test_builder)
-               parser.execute("ancestors: Warrior | parents: false", true)
+               var parser = new CommandParser(test_model, test_main, test_builder)
+               parser.execute("ancestors: Warrior | no-parents", true)
        end
 
        fun test_parents is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("parents: Warrior", true)
        end
 
        fun test_children is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("children: Career", true)
        end
 
        fun test_descendants is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("descendants: Career", true)
        end
 
        fun test_descendants_without_children is test do
-               var parser = new CommandParser(test_view, test_builder)
-               parser.execute("descendants: Career | children: false", true)
+               var parser = new CommandParser(test_model, test_main, test_builder)
+               parser.execute("descendants: Career | no-children", true)
        end
 
        # CmdLin
 
        fun test_lin is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("lin: init | limit: 2", true)
        end
 
        fun test_lin_no_lin is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("lin: test_prog", true)
        end
 
        # CmdSearch
 
        fun test_search is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("search: Caracter | limit: 2", true)
        end
 
        fun test_search_no_query is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("search: | limit: 1", true)
        end
 
        # CmdDefs
 
        fun test_features is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("defs: Character | limit: 3", true)
        end
 
        # CmdCode
 
        fun test_code is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("code: Character", true)
        end
 
        # CmdUsage
 
        fun test_init is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("new: Elf | limit: 2", true)
        end
 
        fun test_call is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("call: endurance_bonus", true)
        end
 
        fun test_return is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("return: Int | limit: 3", true)
        end
 
        fun test_param is test do
-               var parser = new CommandParser(test_view, test_builder)
+               var parser = new CommandParser(test_model, test_main, test_builder)
                parser.execute("param: Career | limit: 3", true)
        end
 
        # CmdCatalog
 
        fun test_term_catalog is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("catalog:", true)
        end
 
        fun test_term_catalog_search is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("search: Caracter | limit: 3", true)
        end
 
        fun test_term_catalog_stats is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("stats:", true)
        end
 
        fun test_term_catalog_tags is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("tags:", true)
        end
 
        fun test_term_catalog_tag is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("tag: game", true)
        end
 
        fun test_term_catalog_maintain is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("maintain: Alexandre Terrasa", true)
        end
 
        fun test_term_catalog_contrib is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("contrib: Alexandre Terrasa", true)
        end
 
        # CmdIni
 
        fun test_term_ini_desc is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-desc: test_prog", true)
        end
 
        fun test_term_ini_git is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-git: test_prog", true)
        end
 
        fun test_term_ini_clone is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("git-clone: test_prog", true)
        end
 
        fun test_term_ini_issues is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-issues: test_prog", true)
        end
 
        fun test_term_ini_maintainer is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-maintainer: test_prog", true)
        end
 
        fun test_term_ini_contributors is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-contributors: test_prog", true)
        end
 
        fun test_term_ini_license is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("ini-license: test_prog", true)
        end
 
        # CmdMain
 
        fun test_term_mains is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("mains: test_prog", true)
        end
 
        fun test_term_main_compile is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("main-compile: test_prog::test_prog", true)
        end
 
        fun test_term_man_synopsis is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("main-run: test_prog::test_prog", true)
        end
 
        fun test_term_man_options is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("main-opts: test_prog::test_prog", true)
        end
 
        fun test_term_testing is test do
-               var parser = new CommandParser(test_view, test_builder, test_catalog)
+               var parser = new CommandParser(test_model, test_main, test_builder, test_catalog)
                parser.execute("testing: test_prog", true)
        end
 end
index ff87303..c7eba98 100644 (file)
@@ -7,14 +7,4 @@ Did you mean?
    class Character
    test_location
 
- + test_prog::character
-   # Characters are playable entity in the world.
-   module character
-   test_location
-
- + test_prog::Career
-   # A `Career` gives a characteristic bonus or malus to the character.
-   abstract class Career
-   test_location
-
 
index 965f6dc..35998c4 100644 (file)
@@ -5,8 +5,3 @@ Search results for `Caracter`:
    class Character
    test_location
 
- + test_prog::character
-   # Characters are playable entity in the world.
-   module character
-   test_location
-
index ae5fe51..35998c4 100644 (file)
@@ -5,13 +5,3 @@ Search results for `Caracter`:
    class Character
    test_location
 
- + test_prog::character
-   # Characters are playable entity in the world.
-   module character
-   test_location
-
- + test_prog::Career
-   # A `Career` gives a characteristic bonus or malus to the character.
-   abstract class Career
-   test_location
-
diff --git a/src/doc/test_doc_commands.nit b/src/doc/test_doc_commands.nit
deleted file mode 100644 (file)
index 82f5e7c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-# 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.
-
-module test_doc_commands is test
-
-import doc_commands
-
-class TestDocCommandParser
-       test
-
-       var parser: DocCommandParser
-
-       fun init_parser is before do
-               parser = new DocCommandParser
-       end
-
-       fun test_empty_string is test do
-               var command = parser.parse("")
-               assert command == null
-               assert parser.errors.length == 1
-               assert parser.errors.first.to_s == "Error: empty command name (col: 0)"
-       end
-
-       fun test_bad_string is test do
-               var command = parser.parse(":")
-               assert command == null
-               assert parser.errors.length == 1
-               assert parser.errors.first.to_s == "Error: empty command name (col: 0)"
-       end
-
-       fun test_unknown_command is test do
-               var command = parser.parse("foo: foo")
-               assert command == null
-               assert parser.errors.length == 1
-               assert parser.errors.first.to_s == "Error: unknown command name (col: 0)"
-       end
-
-       fun test_unallowed_command is test do
-               parser.allowed_commands.clear
-               var command = parser.parse("comment: core::Array")
-               assert command == null
-               assert parser.errors.length == 1
-               assert parser.errors.first.to_s == "Error: unknown command name (col: 0)"
-       end
-
-       fun test_no_arg is test do
-               var command = parser.parse("doc:")
-               assert command == null
-               assert parser.errors.length == 1
-               print parser.errors.first
-               assert parser.errors.first.to_s == "Error: empty command arg (col: 4)"
-       end
-
-       fun test_no_opts is test do
-               var command = parser.parse("doc: core::Array")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert parser.errors.is_empty
-       end
-
-       fun test_opts_empty is test do
-               var command = parser.parse("doc: core::Array | ")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert parser.errors.is_empty
-       end
-
-       fun test_1_opt is test do
-               var command = parser.parse("doc: core::Array | opt1: val1 ")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 1
-               assert command.opts["opt1"] == "val1"
-               assert parser.errors.is_empty
-       end
-
-       fun test_2_opts is test do
-               var command = parser.parse("doc: core::Array | opt1: val1 , opt2: val2,  ")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 2
-               assert command.opts["opt1"] == "val1"
-               assert command.opts["opt2"] == "val2"
-               assert parser.errors.is_empty
-       end
-
-       fun test_empty_opt_name is test do
-               var command = parser.parse("doc: core::Array | opt1: val1  , :")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 1
-               assert command.opts["opt1"] == "val1"
-               assert parser.errors.is_empty
-       end
-
-       fun test_empty_opt_value is test do
-               var command = parser.parse("doc: core::Array | opt1:  , opt2: val2,  ")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 2
-               assert command.opts["opt1"] == ""
-               assert command.opts["opt2"] == "val2"
-               assert parser.errors.is_empty
-       end
-
-       fun test_empty_opt_value2 is test do
-               var command = parser.parse("doc: core::Array | opt1")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 1
-               assert command.opts["opt1"] == ""
-               assert parser.errors.is_empty
-       end
-
-       fun test_empty_opt_value3 is test do
-               var command = parser.parse("doc: core::Array | opt1, opt2: val2")
-               assert command isa CommentCommand
-               assert command.name == "doc"
-               assert command.arg == "core::Array"
-               assert command.opts.length == 2
-               assert command.opts["opt1"] == ""
-               assert command.opts["opt2"] == "val2"
-               assert parser.errors.is_empty
-       end
-end
index 395a57d..1e8a9fb 100644 (file)
@@ -53,7 +53,7 @@ redef class MEntity
        private fun field_separator: String do return "#====#"
        private fun line_separator: String do return "#nnnn#"
 
-       private fun write_doc(view: ModelView, stream: Writer)
+       private fun write_doc(model: Model, mainmodule: MModule, stream: Writer)
        do
                # 1. Short name for autocompletion
                stream.write complete_name
@@ -80,9 +80,9 @@ redef class MEntity
                        stream.write mdoc.content.join(line_separator)
                end
 
-               write_location(view.mainmodule, stream)
+               write_location(mainmodule, stream)
 
-               write_extra_doc(view, stream)
+               write_extra_doc(model, mainmodule, stream)
 
                stream.write "\n"
        end
@@ -96,7 +96,7 @@ redef class MEntity
        private fun complete_mdoc: nullable MDoc do return mdoc
 
        # Extra auto documentation to append to the `stream`
-       private fun write_extra_doc(view: ModelView, stream: Writer) do end
+       private fun write_extra_doc(model: Model, mainmodule: MModule, stream: Writer) do end
 
        # Location (file and line when available) of related declarations
        private fun write_location(mainmodule: MModule, stream: Writer)
@@ -186,13 +186,13 @@ redef class MClassDef
 end
 
 redef class MClassType
-       redef fun write_extra_doc(view, stream)
+       redef fun write_extra_doc(model, mainmodule, stream)
        do
                # Super classes
                stream.write line_separator*2
                stream.write "## Class hierarchy"
 
-               var direct_supers = [for s in mclass.in_hierarchy(view.mainmodule).direct_greaters do s.name]
+               var direct_supers = [for s in mclass.in_hierarchy(mainmodule).direct_greaters do s.name]
                if not direct_supers.is_empty then
                        alpha_comparator.sort direct_supers
                        stream.write line_separator
@@ -200,7 +200,7 @@ redef class MClassType
                        stream.write direct_supers.join(", ")
                end
 
-               var supers = [for s in mclass.in_hierarchy(view.mainmodule).greaters do s.name]
+               var supers = [for s in mclass.in_hierarchy(mainmodule).greaters do s.name]
                supers.remove mclass.name
                if not supers.is_empty then
                        alpha_comparator.sort supers
@@ -209,7 +209,7 @@ redef class MClassType
                        stream.write supers.join(", ")
                end
 
-               var direct_subs = [for s in mclass.in_hierarchy(view.mainmodule).direct_smallers do s.name]
+               var direct_subs = [for s in mclass.in_hierarchy(mainmodule).direct_smallers do s.name]
                if not direct_subs.is_empty then
                        alpha_comparator.sort direct_subs
                        stream.write line_separator
@@ -217,7 +217,7 @@ redef class MClassType
                        stream.write direct_subs.join(", ")
                end
 
-               var subs = [for s in mclass.in_hierarchy(view.mainmodule).smallers do s.name]
+               var subs = [for s in mclass.in_hierarchy(mainmodule).smallers do s.name]
                subs.remove mclass.name
                if not subs.is_empty then
                        alpha_comparator.sort subs
@@ -230,11 +230,11 @@ redef class MClassType
                stream.write line_separator*2
                stream.write "## Properties"
                stream.write line_separator
-               var props = mclass.collect_accessible_mproperties(view).to_a
+               var props = mclass.collect_accessible_mproperties(mainmodule).to_a
                alpha_comparator.sort props
                for prop in props do
                        if mclass.name == "Object" or prop.intro.mclassdef.mclass.name != "Object" then
-                               prop.write_synopsis(view.mainmodule, stream)
+                               prop.write_synopsis(mainmodule, stream)
                        end
                end
        end
@@ -271,9 +271,8 @@ private class AutocompletePhase
 
                # Got all known modules
                var model = mainmodule.model
-               var view = new ModelView(model, mainmodule)
                for mmodule in model.mmodules do
-                       mmodule.write_doc(view, modules_stream)
+                       mmodule.write_doc(model, mainmodule, modules_stream)
                end
 
                # TODO list other modules from the Nit lib
@@ -286,18 +285,18 @@ private class AutocompletePhase
                        # Can it be instantiated?
                        if mclass.kind != interface_kind and mclass.kind != abstract_kind then
 
-                               for prop in mclass.collect_accessible_mproperties(view) do
+                               for prop in mclass.collect_accessible_mproperties(mainmodule) do
                                        if prop isa MMethod and prop.is_init then
                                                mclass_intro.target_constructor = prop.intro
-                                               mclass_intro.write_doc(view, constructors_stream)
+                                               mclass_intro.write_doc(model, mainmodule, constructors_stream)
                                        end
                                end
                                mclass_intro.target_constructor = null
                        end
 
                        # Always add to types and classes
-                       mclass.mclass_type.write_doc(view, classes_stream)
-                       mclass.mclass_type.write_doc(view, types_stream)
+                       mclass.mclass_type.write_doc(model, mainmodule, classes_stream)
+                       mclass.mclass_type.write_doc(model, mainmodule, types_stream)
                end
 
                # Get all known properties
@@ -307,7 +306,7 @@ private class AutocompletePhase
 
                        # Is it a virtual type?
                        if mproperty isa MVirtualTypeProp then
-                               mproperty.intro.write_doc(view, types_stream)
+                               mproperty.intro.write_doc(model, mainmodule, types_stream)
                                continue
                        end
 
@@ -315,7 +314,7 @@ private class AutocompletePhase
                        var first_letter = mproperty.name.chars.first
                        if first_letter == '@' or first_letter == '_' then continue
 
-                       mproperty.intro.write_doc(view, properties_stream)
+                       mproperty.intro.write_doc(model, mainmodule, properties_stream)
                end
 
                # Close streams
@@ -332,10 +331,10 @@ private class AutocompletePhase
 end
 
 redef class MModule
-       redef fun write_extra_doc(view, stream)
+       redef fun write_extra_doc(model, mainmodule, stream)
        do
                # Introduced classes
-               var class_intros = collect_intro_mclasses(view).to_a
+               var class_intros = collect_intro_mclasses.to_a
                if class_intros.not_empty then
                        alpha_comparator.sort class_intros
                        stream.write line_separator*2
@@ -352,7 +351,7 @@ redef class MModule
                # Introduced properties
                var prop_intros = new Array[MPropDef]
                for c in mclassdefs do
-                       prop_intros.add_all c.collect_intro_mpropdefs(view)
+                       prop_intros.add_all c.collect_intro_mpropdefs
                end
 
                if prop_intros.not_empty then
@@ -362,7 +361,7 @@ redef class MModule
                        stream.write line_separator
 
                        for p in prop_intros do
-                               p.mproperty.write_synopsis(view.mainmodule, stream)
+                               p.mproperty.write_synopsis(mainmodule, stream)
                        end
                end
        end
index 84c83a6..78258fa 100644 (file)
@@ -22,7 +22,6 @@ module parse_examples
 import counter
 import typing
 import parse_annotations
-import doc_down
 import model::model_examples
 
 redef class ToolContext
index fbd4803..0153653 100644 (file)
@@ -16,7 +16,7 @@ module test_examples is test
 
 import frontend
 import parse_examples
-import model_views
+import model_collect
 
 class TestExample
        test
@@ -42,13 +42,9 @@ class TestExample
                # process
                modelbuilder.run_phases
                toolcontext.run_global_phases(mmodules)
-               var mainmodule = toolcontext.make_main_module(mmodules)
 
                var filters = new ModelFilter(accept_example = true)
-
-               var view = new ModelView(model, mainmodule, filters)
-
-               for mentity in view.mentities do
+               for mentity in model.collect_mentities(filters) do
                        if not mentity.is_example then continue
 
                        var mexample = mentity.mexample
index 7a1f906..9668a83 100644 (file)
@@ -126,6 +126,14 @@ class HtmlightVisitor
                        end
                end
                if infobox != null and not show_infobox then
+                       var href = infobox.href
+                       if href != null then
+                               # If there is an href, we inject a link around
+                               var tag2 = new HTMLTag("a")
+                               tag2.add tag
+                               tag = tag2
+                               tag.attr("href", href)
+                       end
                        tag.attr("title", infobox.title)
                        tag.classes.add "titled"
                        infobox = null
@@ -568,7 +576,7 @@ redef class MClassType
        redef fun infobox(v)
        do
                var res = new HInfoBox(v, to_s)
-               res.href = v.hrefto(self)
+               res.href = v.hrefto(mclass.intro)
                if not v.show_infobox then return res
                res.new_field("class").add mclass.intro.linkto(v)
                add_doc_to_infobox(res)
diff --git a/src/indexing/code_index.nit b/src/indexing/code_index.nit
new file mode 100644 (file)
index 0000000..765fad0
--- /dev/null
@@ -0,0 +1,204 @@
+# 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.
+
+# An index that contains Nit code
+#
+# Model entities are indexed by their ANode.
+#
+# Vectorization is based on model usage such as:
+# * modules importation
+# * classes spcialization and refinement
+# * methods calls and refinements
+#
+# Example:
+# ~~~nitish
+# # Create the index
+# var index = new CodeIndex(toolcontext)
+# for mentity in mentities do
+#      index.index_mentity(mentity)
+# end
+#
+# # Match a piece of code
+# var matches = index.match_code("print \"Hello, World!\"")
+# for match in matches do
+#      print match
+# end
+# ~~~
+module code_index
+
+import vsm
+import semantize
+import parser_util
+
+# Index for Nit doc
+class CodeIndex
+       super VSMIndex
+
+       redef type DOC: CodeDocument
+
+       # ToolContext used to parse pieces of code
+       var toolcontext: ToolContext
+
+       # Index `mentity`
+       fun index_mentity(mentity: MEntity) do
+               var terms = vectorize_mentity(mentity)
+               var doc = new CodeDocument(mentity, terms)
+               index_document(doc, false)
+       end
+
+       # Match `code` with the index
+       fun match_code(code: String): Array[IndexMatch[DOC]] do
+               var node = parse_code(code)
+               if node == null then return new Array[IndexMatch[DOC]]
+               return match_node(node)
+       end
+
+       # Match `node` with the index
+       fun match_node(node: ANode): Array[IndexMatch[DOC]] do
+               var vector = vectorize_node(node)
+               return match_vector(vector)
+       end
+
+       # Parse a piece of code
+       private fun parse_code(code: String): nullable AModule do
+               # Try to parse code
+               var node = toolcontext.parse_something(code)
+               if not node isa AModule then return null
+
+               # Load code into model
+               var mbuilder = toolcontext.modelbuilder
+               mbuilder.load_rt_module(null, node, "tmp")
+               mbuilder.run_phases
+               return node
+       end
+
+       # Transform `node` in a Vector
+       private fun vectorize_node(node: ANode): Vector do
+               var visitor = new CodeIndexVisitor
+               visitor.enter_visit(node)
+               return visitor.vector
+       end
+
+       # Transform `mentity` in a Vector
+       private fun vectorize_mentity(mentity: MEntity): Vector do
+               var node = toolcontext.modelbuilder.mentity2node(mentity)
+               if node == null then return new Vector
+               return vectorize_node(node)
+       end
+end
+
+# A specific document for mentities code
+class CodeDocument
+       super Document
+       autoinit(mentity, terms_count)
+
+       # MEntity related to this document
+       var mentity: MEntity
+
+       redef var title = mentity.full_name is lazy
+
+       redef var uri = mentity.location.to_s is lazy
+end
+
+# Code index visitor
+#
+# Used to build a VSM Vector from a Nit ANode.
+private class CodeIndexVisitor
+       super Visitor
+
+       var vector = new Vector
+
+       redef fun visit(node) do
+               node.accept_code_index_visitor(self)
+       end
+end
+
+redef class ANode
+       private fun accept_code_index_visitor(v: CodeIndexVisitor) do
+               visit_all(v)
+       end
+end
+
+redef class AStdImport
+       redef fun accept_code_index_visitor(v) do
+               var mmodule = self.mmodule
+               if mmodule != null then
+                       v.vector.inc "import#{mmodule.full_name}"
+               end
+       end
+end
+
+redef class AStdClassdef
+       redef fun accept_code_index_visitor(v) do
+               var mclassdef = self.mclassdef
+               if mclassdef != null then
+                       if not mclassdef.is_intro then
+                               v.vector.inc "redef#{mclassdef.full_name}"
+                               v.vector.inc "redef#{mclassdef.mclass.full_name}"
+                       end
+               end
+               visit_all(v)
+       end
+end
+
+redef class ASuperPropdef
+       redef fun accept_code_index_visitor(v) do
+               var mtype = self.n_type.mtype
+               if mtype isa MClassType then
+                       v.vector.inc "super#{mtype.mclass.intro.full_name}"
+                       v.vector.inc "super#{mtype.mclass.full_name}"
+               end
+       end
+end
+
+redef class APropdef
+       redef fun accept_code_index_visitor(v) do
+               var mpropdef = self.mpropdef
+               if mpropdef != null then
+                       if not mpropdef.is_intro then
+                               v.vector.inc "redef#{mpropdef.mproperty.intro.full_name}"
+                               v.vector.inc "redef#{mpropdef.mproperty.full_name}"
+                       end
+               end
+               visit_all(v)
+       end
+end
+
+redef class ASendExpr
+       redef fun accept_code_index_visitor(v) do
+               var callsite = self.callsite
+               if callsite != null then
+                       var args = callsite.signaturemap.as(not null).map.length
+                       v.vector.inc "call#{callsite.mpropdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mproperty.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mclassdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"
+               end
+               visit_all(v)
+       end
+end
+
+redef class ANewExpr
+       redef fun accept_code_index_visitor(v) do
+               var callsite = self.callsite
+               if callsite != null then
+                       var args = callsite.signaturemap.as(not null).map.length
+                       v.vector.inc "call#{callsite.mpropdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mproperty.full_name}({args})"
+                       v.vector.inc "new#{callsite.mpropdef.mclassdef.full_name}({args})"
+                       v.vector.inc "new#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"
+               end
+               visit_all(v)
+       end
+end
diff --git a/src/indexing/tests/test_code_index.nit b/src/indexing/tests/test_code_index.nit
new file mode 100644 (file)
index 0000000..b2a8f2e
--- /dev/null
@@ -0,0 +1,74 @@
+# 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.
+
+module test_code_index is test
+
+import code_index
+import frontend
+
+class TestCodeIndex
+       test
+
+       # CodeIndex used in tests
+       var test_index: CodeIndex is noinit
+
+       # Initialize test variables
+       #
+       # Must be called before test execution.
+       # FIXME should be before_all
+       fun build_test_env is before do
+               var test_path = "NIT_TESTING_PATH".environ.dirname
+               var test_src = test_path / "../../../tests/test_prog"
+
+               # build model
+               var toolcontext = new ToolContext
+               var model = new Model
+               var modelbuilder = new ModelBuilder(model, toolcontext)
+               var mmodules = modelbuilder.parse_full([test_src])
+               modelbuilder.run_phases
+               toolcontext.run_global_phases(mmodules)
+
+               # create index
+               var index = new CodeIndex(toolcontext)
+               for mmodule in mmodules do
+                       index.index_mentity(mmodule)
+               end
+               test_index = index
+               modelbuilder.paths.add test_src
+       end
+
+       fun test_find1 is test do
+               var query = "import game\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::test_prog"
+       end
+
+       fun test_find2 is test do
+               var query = "import game\nimport rpg\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::game"
+       end
+
+       fun test_find3 is test do
+               var query = "import game\nclass MyGame\nsuper Game\nredef fun start_game do end\nend\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::game_examples"
+       end
+
+       fun test_find_error is test do
+               var query = "error"
+               var matches = test_index.match_code(query)
+               assert matches.is_empty
+       end
+end
index f7b765b..799c413 100644 (file)
@@ -325,7 +325,7 @@ class NaiveInterpreter
        do
                var instance = c_string_instance_len(txt.byte_length+1)
                var val = instance.val
-               val[txt.byte_length] = 0u8
+               val[txt.byte_length] = 0
                txt.to_cstring.copy_to(val, txt.byte_length, 0, 0)
 
                return instance
@@ -1189,10 +1189,10 @@ redef class AMethPropdef
                        var recvval = args.first.val.as(CString)
                        if pname == "[]" then
                                var arg1 = args[1].to_i
-                               return v.byte_instance(recvval[arg1])
+                               return v.int_instance(recvval[arg1])
                        else if pname == "[]=" then
                                var arg1 = args[1].to_i
-                               recvval[arg1] = args[2].val.as(Byte)
+                               recvval[arg1] = args[2].val.as(Int)
                                return null
                        else if pname == "copy_to" then
                                # sig= copy_to(dest: CString, length: Int, from: Int, to: Int)
@@ -1991,8 +1991,9 @@ end
 redef class ACharExpr
        redef fun expr(v)
        do
-               if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
-               if is_code_point then return v.int_instance(self.value.as(not null).code_point)
+               if is_code_point then
+                       return v.int_instance(self.value.as(not null).code_point)
+               end
                return v.char_instance(self.value.as(not null))
        end
 end
index 344bd4d..5146a91 100644 (file)
@@ -129,9 +129,6 @@ redef class ACharExpr
 
        redef fun delimiter_end do return '\''
 
-       # Is the expression returning an ASCII byte value ?
-       fun is_ascii: Bool do return prefix == "b"
-
        # Is the expression returning a Code Point ?
        fun is_code_point: Bool do return prefix == "u"
 
@@ -139,7 +136,6 @@ redef class ACharExpr
 
        redef fun is_valid_augmentation do
                if suffix != "" then return false
-               if is_ascii then return true
                if is_code_point then return true
                if prefix != "" then return false
                return true
@@ -157,7 +153,6 @@ redef class ACharExpr
                        return
                end
                self.value = txt.chars[1]
-               if is_ascii and txt.chars[1].code_point > 127 then v.toolcontext.error(self.hot_location, "Syntax Error: usage of byte prefix on multibyte character.")
        end
 end
 
index cd98e85..e9ec586 100644 (file)
@@ -34,10 +34,10 @@ class CodeSmellsMetricsPhase
        redef fun process_mainmodule(mainmodule, given_mmodules) do
                print toolcontext.format_h1("--- Code Smells Metrics ---")
 
+               var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(private_visibility)
-               var view = new ModelView(toolcontext.modelbuilder.model, mainmodule, filter)
-               self.set_all_average_metrics(view)
-               var mclass_codesmell = new BadConceptonController(view)
+               self.set_all_average_metrics(model)
+               var mclass_codesmell = new BadConceptonController(model, filter)
                var collect = new Counter[MClassDef]
                var mclassdefs = new Array[MClassDef]
 
@@ -51,18 +51,20 @@ class CodeSmellsMetricsPhase
                end
        end
 
-       fun set_all_average_metrics(view: ModelView) do
+       fun set_all_average_metrics(model: Model) do
                var model_builder = toolcontext.modelbuilder
-               self.average_number_of_lines = view.get_avg_linenumber(model_builder)
-               self.average_number_of_parameter = view.get_avg_parameter
-               self.average_number_of_method = view.get_avg_method
-               self.average_number_of_attribute = view.get_avg_attribut
+               self.average_number_of_lines = model.get_avg_linenumber(model_builder)
+               self.average_number_of_parameter = model.get_avg_parameter
+               self.average_number_of_method = model.get_avg_method
+               self.average_number_of_attribute = model.get_avg_attribut
        end
 end
 
 class BadConceptonController
 
-       var view: ModelView
+       var model: Model
+
+       var filter: ModelFilter
 
        # Code smell list
        var bad_conception_elements = new Array[BadConceptionFinder]
@@ -84,7 +86,7 @@ class BadConceptonController
        # Collect method take Array of mclassdef to find the code smells for every class
        fun collect(mclassdefs: Array[MClassDef],phase: CodeSmellsMetricsPhase) do
                for mclassdef in mclassdefs do
-                       var bad_conception_class = new BadConceptionFinder(mclassdef, phase, view)
+                       var bad_conception_class = new BadConceptionFinder(mclassdef, phase, model, filter)
                        bad_conception_class.collect
                        bad_conception_elements.add(bad_conception_class)
                end
@@ -117,18 +119,19 @@ class BadConceptionFinder
        var mclassdef: MClassDef
        var array_badconception = new Array[BadConception]
        var phase: CodeSmellsMetricsPhase
-       var view: ModelView
+       var model: Model
+       var filter: ModelFilter
        var score = 0.0
 
        # Collect code smell with selected toolcontext option
        fun collect do
                var bad_conception_elements = new Array[BadConception]
                # Check toolcontext option
-               if phase.toolcontext.opt_feature_envy.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new FeatureEnvy(phase, view))
-               if phase.toolcontext.opt_long_method.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongMethod(phase, view))
-               if phase.toolcontext.opt_long_params.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongParameterList(phase, view))
-               if phase.toolcontext.opt_no_abstract_implementation.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new NoAbstractImplementation(phase, view))
-               if phase.toolcontext.opt_large_class.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LargeClass(phase, view))
+               if phase.toolcontext.opt_feature_envy.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new FeatureEnvy(phase, model, filter))
+               if phase.toolcontext.opt_long_method.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongMethod(phase, model, filter))
+               if phase.toolcontext.opt_long_params.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LongParameterList(phase, model, filter))
+               if phase.toolcontext.opt_no_abstract_implementation.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new NoAbstractImplementation(phase, model, filter))
+               if phase.toolcontext.opt_large_class.value or phase.toolcontext.opt_all.value then bad_conception_elements.add(new LargeClass(phase, model, filter))
                # Collected all code smell if their state is true
                for bad_conception_element in bad_conception_elements do
                        if bad_conception_element.collect(self.mclassdef,phase.toolcontext.modelbuilder) then array_badconception.add(bad_conception_element)
@@ -159,7 +162,9 @@ end
 abstract class BadConception
        var phase: CodeSmellsMetricsPhase
 
-       var view: ModelView
+       var model: Model
+
+       var filter: ModelFilter
 
        var score = 0.0
 
@@ -192,9 +197,9 @@ class LargeClass
        redef fun desc do return "Large class"
 
        redef fun collect(mclassdef, model_builder): Bool do
-               self.number_attribut = mclassdef.collect_intro_and_redef_mattributes(view).length
+               self.number_attribut = mclassdef.collect_intro_and_redef_mattributes(filter).length
                # Get the number of methods (Accessor include) (subtract the get and set of attibutes with (numberAtribut*2))
-               self.number_method = mclassdef.collect_intro_and_redef_methods(view).length
+               self.number_method = mclassdef.collect_intro_and_redef_methods(filter).length
                self.score_rate
                return self.number_method.to_f > phase.average_number_of_method and self.number_attribut.to_f > phase.average_number_of_attribute
        end
@@ -217,7 +222,7 @@ class LongParameterList
        redef fun desc do return "Long parameter list"
 
        redef fun collect(mclassdef, model_builder): Bool do
-               for meth in mclassdef.collect_intro_and_redef_mpropdefs(view) do
+               for meth in mclassdef.collect_intro_and_redef_mpropdefs(filter) do
                        var threshold_value = 4
                        # Get the threshold value from the toolcontext command
                        if phase.toolcontext.opt_long_params_threshold.value != 0 then threshold_value = phase.toolcontext.opt_long_params_threshold.value
@@ -258,7 +263,7 @@ class FeatureEnvy
        redef fun desc do return "Feature envy"
 
        redef fun collect(mclassdef, model_builder): Bool do
-               var mmethoddefs = call_analyze_methods(mclassdef,model_builder, view)
+               var mmethoddefs = call_analyze_methods(mclassdef,model_builder, filter)
                for mmethoddef in mmethoddefs do
                        var max_class_call = mmethoddef.class_call.max
                        # Check if the class with the maximum call is >= auto-call and the maximum call class is != of this class
@@ -303,7 +308,7 @@ class LongMethod
        redef fun desc do return "Long method"
 
        redef fun collect(mclassdef, model_builder): Bool do
-               var mmethoddefs = call_analyze_methods(mclassdef,model_builder, view)
+               var mmethoddefs = call_analyze_methods(mclassdef,model_builder, filter)
                var threshold_value = phase.average_number_of_lines.to_i
                # Get the threshold value from the toolcontext command
                if phase.toolcontext.opt_long_method_threshold.value != 0 then threshold_value = phase.toolcontext.opt_long_method_threshold.value
@@ -343,8 +348,8 @@ class NoAbstractImplementation
 
        redef fun collect(mclassdef, model_builder): Bool do
                if not mclassdef.mclass.is_abstract and not mclassdef.mclass.is_interface then
-                       if mclassdef.collect_abstract_methods(view).not_empty then
-                               bad_methods.add_all(mclassdef.collect_not_define_properties(view))
+                       if mclassdef.collect_abstract_methods(filter).not_empty then
+                               bad_methods.add_all(mclassdef.collect_not_define_properties(filter))
                        end
                end
                self.score_rate
@@ -368,11 +373,12 @@ class NoAbstractImplementation
        end
 end
 
-redef class ModelView
+redef class Model
        fun get_avg_parameter: Float do
                var counter = new Counter[MMethodDef]
-               for mclassdef in mclassdefs do
-                       for method in mclassdef.collect_intro_and_redef_mpropdefs(self) do
+               var filter = new ModelFilter
+               for mclassdef in collect_mclassdefs(filter) do
+                       for method in mclassdef.collect_intro_and_redef_mpropdefs(filter) do
                        # check if the property is a method definition
                                if not method isa MMethodDef then continue
                                #Check if method has a signature
@@ -386,8 +392,9 @@ redef class ModelView
 
        fun get_avg_attribut: Float do
                var counter = new Counter[MClassDef]
-               for mclassdef in mclassdefs do
-                       var number_attributs = mclassdef.collect_intro_and_redef_mattributes(self).length
+               var filter = new ModelFilter
+               for mclassdef in collect_mclassdefs(filter) do
+                       var number_attributs = mclassdef.collect_intro_and_redef_mattributes(filter).length
                        if number_attributs != 0 then counter[mclassdef] = number_attributs
                end
                return counter.avg + counter.std_dev
@@ -395,8 +402,9 @@ redef class ModelView
 
        fun get_avg_method: Float do
                var counter = new Counter[MClassDef]
-               for mclassdef in mclassdefs do
-                       var number_methodes = mclassdef.collect_intro_and_redef_methods(self).length
+               var filter = new ModelFilter
+               for mclassdef in collect_mclassdefs(filter) do
+                       var number_methodes = mclassdef.collect_intro_and_redef_methods(filter).length
                        if number_methodes != 0 then counter[mclassdef] = number_methodes
                end
                return counter.avg + counter.std_dev
@@ -404,15 +412,16 @@ redef class ModelView
 
        fun get_avg_linenumber(model_builder: ModelBuilder): Float do
                var methods_analyse_metrics = new Counter[MClassDef]
-               for mclassdef in mclassdefs do
+               var filter = new ModelFilter
+               for mclassdef in collect_mclassdefs(filter) do
                        var result = 0
                        var count = 0
-                       for mmethoddef in call_analyze_methods(mclassdef,model_builder, self) do
+                       for mmethoddef in call_analyze_methods(mclassdef,model_builder, filter) do
                                result += mmethoddef.line_number
                                if mmethoddef.line_number == 0 then continue
                                count += 1
                        end
-                       if not mclassdef.collect_local_mproperties(self).length != 0 then continue
+                       if not mclassdef.collect_local_mproperties(filter).length != 0 then continue
                        if count == 0 then continue
                        methods_analyse_metrics[mclassdef] = (result/count).to_i
                end
index 29a15ce..527ece8 100644 (file)
@@ -38,28 +38,28 @@ private class InheritanceMetricsPhase
                out.mkdir
 
                var model = toolcontext.modelbuilder.model
-               var model_view = new ModelView(model, mainmodule)
+               var filter = new ModelFilter(min_visibility = private_visibility)
 
                print toolcontext.format_h1("\n# Inheritance metrics")
 
                var hmetrics = new MetricSet
-               hmetrics.register(new MDUI(model_view))
-               hmetrics.register(new MDUIC(model_view))
-               hmetrics.register(new MDUII(model_view))
-               hmetrics.register(new MIF(model_view))
-               hmetrics.register(new MIFC(model_view))
-               hmetrics.register(new MIFI(model_view))
+               hmetrics.register(new MDUI(model, mainmodule))
+               hmetrics.register(new MDUIC(model, mainmodule))
+               hmetrics.register(new MDUII(model, mainmodule))
+               hmetrics.register(new MIF(model, mainmodule))
+               hmetrics.register(new MIFC(model, mainmodule))
+               hmetrics.register(new MIFI(model, mainmodule))
 
                var cmetrics = new MetricSet
-               cmetrics.register(new CNOAC(model_view))
-               cmetrics.register(new CNOPC(model_view))
-               cmetrics.register(new CNOCC(model_view))
-               cmetrics.register(new CNODC(model_view))
-               cmetrics.register(new CNOPI(model_view))
-               cmetrics.register(new CNOCI(model_view))
-               cmetrics.register(new CNODI(model_view))
-               cmetrics.register(new CDITC(model_view))
-               cmetrics.register(new CDITI(model_view))
+               cmetrics.register(new CNOAC(model, mainmodule, filter))
+               cmetrics.register(new CNOPC(model, mainmodule, filter))
+               cmetrics.register(new CNOCC(model, mainmodule, filter))
+               cmetrics.register(new CNODC(model, mainmodule, filter))
+               cmetrics.register(new CNOPI(model, mainmodule, filter))
+               cmetrics.register(new CNOCI(model, mainmodule, filter))
+               cmetrics.register(new CNODI(model, mainmodule, filter))
+               cmetrics.register(new CDITC(model, mainmodule, filter))
+               cmetrics.register(new CDITI(model, mainmodule, filter))
 
                var mmodules = new HashSet[MModule]
                var mclasses = new HashSet[MClass]
@@ -116,7 +116,7 @@ class MDUI
                for mmodule in mmodules do
                        var count = 0
                        for mclass in mmodule.intro_mclasses do
-                               if mclass.in_hierarchy(model_view.mainmodule).greaters.length > 2 then count += 1
+                               if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                        end
                        if mmodule.intro_mclasses.is_empty then
                                values[mmodule] = 0.0
@@ -142,7 +142,7 @@ class MDUIC
                        var nb = 0
                        for mclass in mmodule.intro_mclasses do
                                if mclass.kind == abstract_kind or mclass.kind == concrete_kind or mclass.kind == extern_kind then
-                                       if mclass.in_hierarchy(model_view.mainmodule).greaters.length > 2 then count += 1
+                                       if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                                end
                                nb += 1
                        end
@@ -170,7 +170,7 @@ class MDUII
                        var nb = 0
                        for mclass in mmodule.intro_mclasses do
                                if mclass.kind == interface_kind then
-                                       if mclass.in_hierarchy(model_view.mainmodule).greaters.length > 2 then count += 1
+                                       if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                                end
                                nb += 1
                        end
@@ -196,7 +196,7 @@ class MIF
                for mmodule in mmodules do
                        var count = 0
                        for mclass in mmodule.intro_mclasses do
-                               if mclass.in_hierarchy(model_view.mainmodule).direct_smallers.length > 0 then count += 1
+                               if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                        end
                        if mmodule.intro_mclasses.is_empty then
                                values[mmodule] = 0.0
@@ -222,7 +222,7 @@ class MIFC
                        var nb = 0
                        for mclass in mmodule.intro_mclasses do
                                if mclass.kind == abstract_kind or mclass.kind == concrete_kind or mclass.kind == extern_kind then
-                                       if mclass.in_hierarchy(model_view.mainmodule).direct_smallers.length > 0 then count += 1
+                                       if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                                end
                                nb += 1
                        end
@@ -250,7 +250,7 @@ class MIFI
                        var nb = 0
                        for mclass in mmodule.intro_mclasses do
                                if mclass.kind == interface_kind then
-                                       if mclass.in_hierarchy(model_view.mainmodule).direct_smallers.length > 0 then count += 1
+                                       if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                                end
                                nb += 1
                        end
@@ -275,7 +275,7 @@ class CNOAC
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).greaters do
+                       for parent in mclass.in_hierarchy(mainmodule).greaters do
                                if parent == mclass then continue
                                if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
                                        count += 1
@@ -298,7 +298,7 @@ class CNOPC
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).direct_greaters do
+                       for parent in mclass.in_hierarchy(mainmodule).direct_greaters do
                                if parent == mclass then continue
                                if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
                                        count += 1
@@ -321,7 +321,7 @@ class CNOCC
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).direct_smallers do
+                       for parent in mclass.in_hierarchy(mainmodule).direct_smallers do
                                if parent == mclass then continue
                                if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
                                        count += 1
@@ -344,7 +344,7 @@ class CNODC
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).smallers do
+                       for parent in mclass.in_hierarchy(mainmodule).smallers do
                                if parent == mclass then continue
                                if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
                                        count += 1
@@ -367,7 +367,7 @@ class CNOAA
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).greaters do
+                       for parent in mclass.in_hierarchy(mainmodule).greaters do
                                if parent == mclass then continue
                                if parent.kind == abstract_kind then
                                        count += 1
@@ -390,7 +390,7 @@ class CNOAI
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).greaters do
+                       for parent in mclass.in_hierarchy(mainmodule).greaters do
                                if parent == mclass then continue
                                if parent.kind == interface_kind then
                                        count += 1
@@ -413,7 +413,7 @@ class CNOPI
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).direct_greaters do
+                       for parent in mclass.in_hierarchy(mainmodule).direct_greaters do
                                if parent == mclass then continue
                                if parent.kind == interface_kind then
                                        count += 1
@@ -436,7 +436,7 @@ class CNOCI
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).direct_smallers do
+                       for parent in mclass.in_hierarchy(mainmodule).direct_smallers do
                                if parent == mclass then continue
                                if parent.kind == interface_kind then
                                        count += 1
@@ -459,7 +459,7 @@ class CNODI
        redef fun collect(mclasses) do
                for mclass in mclasses do
                        var count = 0
-                       for parent in mclass.in_hierarchy(model_view.mainmodule).smallers do
+                       for parent in mclass.in_hierarchy(mainmodule).smallers do
                                if parent == mclass then continue
                                if parent.kind == interface_kind then
                                        count += 1
@@ -481,7 +481,7 @@ class CDITC
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.ditc(model_view.mainmodule)
+                       values[mclass] = mclass.ditc(mainmodule)
                end
        end
 end
@@ -497,7 +497,7 @@ class CDITI
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.diti(model_view.mainmodule)
+                       values[mclass] = mclass.diti(mainmodule)
                end
        end
 end
index 84537ce..98a4412 100644 (file)
@@ -18,155 +18,154 @@ module mclassdef_collect
 # We usualy need specific phases
 # NOTE: `frontend` is sufficent in most case (it is often too much)
 import frontend
-import model_views
 import model_collect
 
 redef class MClassDef
        # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
-       fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_intro_mproperties(filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                        for mprop in self.intro_mproperties do
-                               if not view.accept_mentity(mprop) then continue
+                               if not filter.accept_mentity(mprop) then continue
                                set.add(mprop)
                        end
                return set
        end
 
        # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
-       fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_intro_mmethods(filter: ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_intro_mproperties(filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
        end
 
        # Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
-       fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_redef_mmethods(filter: ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_redef_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_redef_mproperties(filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
        end
 
        # Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
-       fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_redef_mattributes(filter: ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_redef_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_redef_mproperties(filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
-       fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_intro_mattributes(filter: ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_intro_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_intro_mproperties(filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
-       fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_redef_mproperties(filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                for mpropdef in self.mpropdefs do
-                       if not view.accept_mentity(mpropdef) then continue
+                       if not filter.accept_mentity(mpropdef) then continue
                        if mpropdef.mproperty.intro_mclassdef.mclass == self then continue
                                set.add(mpropdef.mproperty)
                        end
                return set
        end
 
-       # Collect mmethods inherited by 'self' if accepted by `view`.
-       fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do
+       # Collect mmethods inherited by 'self' if accepted by `filter`.
+       fun collect_inherited_mmethods(mainmodule: MModule, filter: ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_inherited_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_inherited_mproperties(mainmodule, filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
        end
 
        # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
-       fun collect_local_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_local_mproperties(filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
-               set.add_all collect_intro_mproperties(view)
-               set.add_all collect_redef_mproperties(view)
+               set.add_all collect_intro_mproperties(filter)
+               set.add_all collect_redef_mproperties(filter)
                return set
        end
 
        # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
-       fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_inherited_mproperties(mainmodule: MModule, filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
-               for parent in collect_parents(view) do
-                       set.add_all(parent.collect_intro_mproperties(view))
-                       set.add_all(parent.collect_inherited_mproperties(view))
+               for parent in collect_parents(mainmodule, filter) do
+                       set.add_all(parent.collect_intro_mproperties(filter))
+                       set.add_all(parent.collect_inherited_mproperties(mainmodule, filter))
                end
                return set
        end
 
        # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
-       fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_inherited_mattributes(mainmodule: MModule, filter: ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_inherited_mproperties(view) do
-                       if not view.accept_mentity(mproperty) then continue
+               for mproperty in collect_inherited_mproperties(mainmodule, filter) do
+                       if not filter.accept_mentity(mproperty) then continue
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect all mmethod inehrited,intro and redef
-       fun collect_all_methods(view: ModelView): Set[MMethod] do
+       fun collect_all_methods(mainmodule: MModule, filter: ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all collect_intro_mmethods(view)
-               set.add_all collect_redef_mmethods(view)
-               set.add_all collect_inherited_mmethods(view)
+               set.add_all collect_intro_mmethods(filter)
+               set.add_all collect_redef_mmethods(filter)
+               set.add_all collect_inherited_mmethods(mainmodule, filter)
                return set
        end
 
        # Collect all mattributs inehrited,intro and redef
-       fun collect_all_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_all_mattributes(mainmodule: MModule, filter: ModelFilter): Set[MAttribute] do
                var set = new HashSet[MAttribute]
-               set.add_all collect_redef_mattributes(view)
-               set.add_all collect_intro_mattributes(view)
-               set.add_all collect_inherited_mattributes(view)
+               set.add_all collect_redef_mattributes(filter)
+               set.add_all collect_intro_mattributes(filter)
+               set.add_all collect_inherited_mattributes(mainmodule, filter)
                return set
        end
 
        # Collect intro and redef mmethods
-       fun collect_intro_and_redef_methods(view: ModelView): Set[MMethod] do
+       fun collect_intro_and_redef_methods(filter: ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all collect_intro_mmethods(view)
-               set.add_all collect_redef_mmethods(view)
+               set.add_all collect_intro_mmethods(filter)
+               set.add_all collect_redef_mmethods(filter)
                return set
        end
 
        # Collect intro and redef mattributs
-       fun collect_intro_and_redef_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_intro_and_redef_mattributes(filter: ModelFilter): Set[MAttribute] do
                var set = new HashSet[MAttribute]
-               set.add_all collect_redef_mattributes(view)
-               set.add_all collect_intro_mattributes(view)
+               set.add_all collect_redef_mattributes(filter)
+               set.add_all collect_intro_mattributes(filter)
                return set
        end
 
        # Collect intro and redef mpropdefs
-       fun collect_intro_and_redef_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_intro_and_redef_mpropdefs(filter: ModelFilter): Set[MPropDef] do
                var set = new HashSet[MPropDef]
-               set.add_all collect_intro_mpropdefs(view)
-               set.add_all collect_redef_mpropdefs(view)
+               set.add_all collect_intro_mpropdefs(filter)
+               set.add_all collect_redef_mpropdefs(filter)
                return set
        end
 
        # Collect intro abstract mmethodDef
-       fun collect_abstract_methods(view: ModelView): Set[MMethodDef] do
+       fun collect_abstract_methods(filter: ModelFilter): Set[MMethodDef] do
                var set = new HashSet[MMethodDef]
-               var mpropdefs = collect_intro_mpropdefs(view)
+               var mpropdefs = collect_intro_mpropdefs(filter)
                for mpropdef in mpropdefs do
                        if mpropdef isa MMethodDef then
                                if mpropdef.is_abstract then set.add(mpropdef)
@@ -176,9 +175,9 @@ redef class MClassDef
        end
 
        # Collect not defined properties
-       fun collect_not_define_properties(view: ModelView):Set[MMethodDef] do
+       fun collect_not_define_properties(filter: ModelFilter):Set[MMethodDef] do
                var set = new HashSet[MMethodDef]
-               for mpropdef in collect_abstract_methods(view) do
+               for mpropdef in collect_abstract_methods(filter) do
                        var redef_count = 0
                        for mprop in mpropdef.mproperty.mpropdefs do
                                if mprop.is_abstract then continue
index 158a448..2404a38 100644 (file)
@@ -38,24 +38,23 @@ private class MClassesMetricsPhase
 
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(private_visibility)
-               var model_view = new ModelView(model, mainmodule, filter)
 
                print toolcontext.format_h1("\n# MClasses metrics")
 
                var metrics = new MetricSet
-               metrics.register(new CNOA(model_view))
-               metrics.register(new CNOP(model_view))
-               metrics.register(new CNOC(model_view))
-               metrics.register(new CNOD(model_view))
-               metrics.register(new CDIT(model_view))
-               metrics.register(new CNBP(model_view))
-               metrics.register(new CNBA(model_view))
-               metrics.register(new CNBI(model_view))
-               metrics.register(new CNBM(model_view))
-               metrics.register(new CNBV(model_view))
-               metrics.register(new CNBIP(model_view))
-               metrics.register(new CNBRP(model_view))
-               metrics.register(new CNBHP(model_view))
+               metrics.register(new CNOA(model, mainmodule, filter))
+               metrics.register(new CNOP(model, mainmodule, filter))
+               metrics.register(new CNOC(model, mainmodule, filter))
+               metrics.register(new CNOD(model, mainmodule, filter))
+               metrics.register(new CDIT(model, mainmodule, filter))
+               metrics.register(new CNBP(model, mainmodule, filter))
+               metrics.register(new CNBA(model, mainmodule, filter))
+               metrics.register(new CNBI(model, mainmodule, filter))
+               metrics.register(new CNBM(model, mainmodule, filter))
+               metrics.register(new CNBV(model, mainmodule, filter))
+               metrics.register(new CNBIP(model, mainmodule, filter))
+               metrics.register(new CNBRP(model, mainmodule, filter))
+               metrics.register(new CNBHP(model, mainmodule, filter))
 
                var mclasses = new HashSet[MClass]
                for mpackage in model.mpackages do
@@ -93,8 +92,14 @@ abstract class MClassMetric
        super Metric
        redef type ELM: MClass
 
-       # Model view used to collect and filter entities
-       var model_view: ModelView
+       # Model used to collect and filter entities
+       var model: Model
+
+       # Mainmodule for class linearization
+       var mainmodule: MModule
+
+       # Filter to apply
+       var filter: nullable ModelFilter
 end
 
 # Class Metric: Number of Ancestors
@@ -106,7 +111,7 @@ class CNOA
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.in_hierarchy(model_view.mainmodule).greaters.length - 1
+                       values[mclass] = mclass.in_hierarchy(mainmodule).greaters.length - 1
                end
        end
 end
@@ -120,7 +125,7 @@ class CNOP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.in_hierarchy(model_view.mainmodule).direct_greaters.length
+                       values[mclass] = mclass.in_hierarchy(mainmodule).direct_greaters.length
                end
        end
 end
@@ -134,7 +139,7 @@ class CNOC
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.in_hierarchy(model_view.mainmodule).direct_smallers.length
+                       values[mclass] = mclass.in_hierarchy(mainmodule).direct_smallers.length
                end
        end
 end
@@ -148,7 +153,7 @@ class CNOD
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.in_hierarchy(model_view.mainmodule).smallers.length - 1
+                       values[mclass] = mclass.in_hierarchy(mainmodule).smallers.length - 1
                end
        end
 end
@@ -162,7 +167,7 @@ class CDIT
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.in_hierarchy(model_view.mainmodule).depth
+                       values[mclass] = mclass.in_hierarchy(mainmodule).depth
                end
        end
 end
@@ -176,7 +181,7 @@ class CNBP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_accessible_mproperties(model_view).length
+                       values[mclass] = mclass.collect_accessible_mproperties(mainmodule, filter).length
                end
        end
 end
@@ -190,7 +195,7 @@ class CNBA
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_accessible_mattributes(model_view).length
+                       values[mclass] = mclass.collect_accessible_mattributes(mainmodule, filter).length
                end
        end
 end
@@ -204,7 +209,7 @@ class CNBM
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_accessible_mmethods(model_view).length
+                       values[mclass] = mclass.collect_accessible_mmethods(mainmodule, filter).length
                end
        end
 end
@@ -218,7 +223,7 @@ class CNBI
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_accessible_inits(model_view).length
+                       values[mclass] = mclass.collect_accessible_inits(mainmodule, filter).length
                end
        end
 end
@@ -232,7 +237,7 @@ class CNBV
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_accessible_vts(model_view).length
+                       values[mclass] = mclass.collect_accessible_vts(mainmodule, filter).length
                end
        end
 end
@@ -246,7 +251,7 @@ class CNBIP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_intro_mproperties(model_view).length
+                       values[mclass] = mclass.collect_intro_mproperties(filter).length
                end
        end
 end
@@ -260,7 +265,7 @@ class CNBRP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_redef_mproperties(model_view).length
+                       values[mclass] = mclass.collect_redef_mproperties(filter).length
                end
        end
 end
@@ -274,7 +279,7 @@ class CNBHP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_inherited_mproperties(model_view).length
+                       values[mclass] = mclass.collect_inherited_mproperties(mainmodule, filter).length
                end
        end
 end
@@ -288,7 +293,7 @@ class CNBLP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.collect_local_mproperties(model_view).length
+                       values[mclass] = mclass.collect_local_mproperties(filter).length
                end
        end
 end
index e16e75f..2fe74a2 100644 (file)
@@ -68,17 +68,16 @@ private class MendelMetricsPhase
 
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(min_visibility = protected_visibility)
-               var model_view = new ModelView(model, mainmodule, filter)
 
                var mclasses = new HashSet[MClass]
-               for mclass in model_view.mclasses do
+               for mclass in model.collect_mclasses(filter) do
                        if mclass.is_interface then continue
                        mclasses.add(mclass)
                end
 
-               var cnblp = new CNBLP(model_view)
-               var cnvi = new CNVI(model_view)
-               var cnvs = new CNVS(model_view)
+               var cnblp = new CNBLP(model, mainmodule, filter)
+               var cnvi = new CNVI(model, mainmodule, filter)
+               var cnvs = new CNVS(model, mainmodule, filter)
 
                var metrics = new MetricSet
                metrics.register(cnblp, cnvi, cnvs)
@@ -114,15 +113,15 @@ private class MendelMetricsPhase
                        csvh.separator = ';'
                        csvh.header = ["povr", "ovr", "pext", "ext", "pspe", "spe", "prep", "rep", "eq"]
                        for mclass in mclasses do
-                               var povr = mclass.is_pure_overrider(model_view).object_id
-                               var ovr = mclass.is_overrider(model_view).object_id
-                               var pext = mclass.is_pure_extender(model_view).object_id
-                               var ext = mclass.is_extender(model_view).object_id
-                               var pspe = mclass.is_pure_specializer(model_view).object_id
-                               var spe = mclass.is_pure_specializer(model_view).object_id
-                               var prep = mclass.is_pure_replacer(model_view).object_id
-                               var rep = mclass.is_replacer(model_view).object_id
-                               var eq = mclass.is_equal(model_view).object_id
+                               var povr = mclass.is_pure_overrider(filter).object_id
+                               var ovr = mclass.is_overrider(filter).object_id
+                               var pext = mclass.is_pure_extender(filter).object_id
+                               var ext = mclass.is_extender(filter).object_id
+                               var pspe = mclass.is_pure_specializer(filter).object_id
+                               var spe = mclass.is_pure_specializer(filter).object_id
+                               var prep = mclass.is_pure_replacer(filter).object_id
+                               var rep = mclass.is_replacer(filter).object_id
+                               var eq = mclass.is_equal(filter).object_id
                                csvh.add_record(povr, ovr, pext, ext, pspe, spe, prep, rep, eq)
                        end
                        csvh.write_to_file("{out}/inheritance_behaviour.csv")
@@ -140,8 +139,8 @@ class CBMS
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       var totc = mclass.collect_accessible_mproperties(model_view).length
-                       var ditc = mclass.in_hierarchy(model_view.mainmodule).depth
+                       var totc = mclass.collect_accessible_mproperties(mainmodule, filter).length
+                       var ditc = mclass.in_hierarchy(mainmodule).depth
                        values[mclass] = totc.to_f / (ditc + 1).to_f
                end
        end
@@ -157,8 +156,8 @@ class MBMS
 
        redef fun collect(mmodules) do
                for mmodule in mmodules do
-                       var totc = mmodule.collect_intro_mclassdefs(model_view).length
-                       totc += mmodule.collect_redef_mclassdefs(model_view).length
+                       var totc = mmodule.collect_intro_mclassdefs(filter).length
+                       totc += mmodule.collect_redef_mclassdefs(filter).length
                        var ditc = mmodule.in_importation.depth
                        values[mmodule] = totc.to_f / (ditc + 1).to_f
                end
@@ -174,15 +173,15 @@ class CNVI
        redef fun desc do return "class novelty index, contribution of the class to its branch in term of introductions"
 
        redef fun collect(mclasses) do
-               var cbms = new CBMS(model_view)
+               var cbms = new CBMS(model, mainmodule, filter)
                for mclass in mclasses do
                        # compute branch mean size
-                       var parents = mclass.in_hierarchy(model_view.mainmodule).direct_greaters
+                       var parents = mclass.in_hierarchy(mainmodule).direct_greaters
                        if parents.length > 0 then
                                cbms.clear
                                cbms.collect(new HashSet[MClass].from(parents))
                                # compute class novelty index
-                               var locc = mclass.collect_accessible_mproperties(model_view).length
+                               var locc = mclass.collect_accessible_mproperties(mainmodule, filter).length
                                values[mclass] = locc.to_f / cbms.avg
                        else
                                values[mclass] = 0.0
@@ -200,7 +199,7 @@ class MNVI
        redef fun desc do return "module novelty index, contribution of the module to its branch in term of introductions"
 
        redef fun collect(mmodules) do
-               var mbms = new MBMS(model_view)
+               var mbms = new MBMS(model, mainmodule, filter)
                for mmodule in mmodules do
                        # compute branch mean size
                        var parents = mmodule.in_importation.direct_greaters
@@ -208,8 +207,8 @@ class MNVI
                                mbms.clear
                                mbms.collect(new HashSet[MModule].from(parents))
                                # compute module novelty index
-                               var locc = mmodule.collect_intro_mclassdefs(model_view).length
-                               locc += mmodule.collect_redef_mclassdefs(model_view).length
+                               var locc = mmodule.collect_intro_mclassdefs(filter).length
+                               locc += mmodule.collect_redef_mclassdefs(filter).length
                                values[mmodule] = locc.to_f / mbms.avg
                        else
                                values[mmodule] = 0.0
@@ -227,10 +226,10 @@ class CNVS
        redef fun desc do return "class novelty score, importance of the contribution of the class to its branch"
 
        redef fun collect(mclasses) do
-               var cnvi = new CNVI(model_view)
+               var cnvi = new CNVI(model, mainmodule, filter)
                cnvi.collect(mclasses)
                for mclass in mclasses do
-                       var locc = mclass.collect_local_mproperties(model_view).length
+                       var locc = mclass.collect_local_mproperties(filter).length
                        values[mclass] = cnvi.values[mclass] * locc.to_f
                end
        end
@@ -245,11 +244,11 @@ class MNVS
        redef fun desc do return "module novelty score, importance of the contribution of the module to its branch"
 
        redef fun collect(mmodules) do
-               var mnvi = new MNVI(model_view)
+               var mnvi = new MNVI(model, mainmodule, filter)
                mnvi.collect(mmodules)
                for mmodule in mmodules do
-                       var locc = mmodule.collect_intro_mclassdefs(model_view).length
-                       locc += mmodule.collect_redef_mclassdefs(model_view).length
+                       var locc = mmodule.collect_intro_mclassdefs(filter).length
+                       locc += mmodule.collect_redef_mclassdefs(filter).length
                        values[mmodule] = mnvi.values[mmodule] * locc.to_f
                end
        end
@@ -257,11 +256,11 @@ end
 
 redef class MClass
        # the set of redefition that call to super
-       fun extended_mproperties(view: ModelView): Set[MProperty] do
+       fun extended_mproperties(filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                for mclassdef in mclassdefs do
                        for mpropdef in mclassdef.mpropdefs do
-                               if not view.accept_mentity(mpropdef) then continue
+                               if not filter.accept_mentity(mpropdef) then continue
                                if not mpropdef.has_supercall then continue
                                if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
                        end
@@ -270,11 +269,11 @@ redef class MClass
        end
 
        # the set of redefition that do not call to super
-       fun overriden_mproperties(view: ModelView): Set[MProperty] do
+       fun overriden_mproperties(filter: ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                for mclassdef in mclassdefs do
                        for mpropdef in mclassdef.mpropdefs do
-                               if not view.accept_mentity(mpropdef) then continue
+                               if not filter.accept_mentity(mpropdef) then continue
                                if mpropdef.has_supercall then continue
                                if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
                        end
@@ -283,78 +282,78 @@ redef class MClass
        end
 
        # pure overriders contain only redefinitions
-       private fun is_pure_overrider(view: ModelView): Bool do
-               var news = collect_intro_mproperties(view).length
-               var locs = collect_local_mproperties(view).length
+       private fun is_pure_overrider(filter: ModelFilter): Bool do
+               var news = collect_intro_mproperties(filter).length
+               var locs = collect_local_mproperties(filter).length
                if news == 0 and locs > 0 then return true
                return false
        end
 
        # overriders contain more definitions than introductions
-       private fun is_overrider(view: ModelView): Bool do
-               var rdfs = collect_redef_mproperties(view).length
-               var news = collect_intro_mproperties(view).length
-               var locs = collect_local_mproperties(view).length
+       private fun is_overrider(filter: ModelFilter): Bool do
+               var rdfs = collect_redef_mproperties(filter).length
+               var news = collect_intro_mproperties(filter).length
+               var locs = collect_local_mproperties(filter).length
                if rdfs >= news and locs > 0 then return true
                return false
        end
 
        # pure extenders contain only introductions
-       private fun is_pure_extender(view: ModelView): Bool do
-               var rdfs = collect_redef_mproperties(view).length
-               var locs = collect_local_mproperties(view).length
+       private fun is_pure_extender(filter: ModelFilter): Bool do
+               var rdfs = collect_redef_mproperties(filter).length
+               var locs = collect_local_mproperties(filter).length
                if rdfs == 0 and locs > 0 then return true
                return false
        end
 
        # extenders contain more introduction than redefinitions
-       private fun is_extender(view: ModelView): Bool do
-               var rdfs = collect_redef_mproperties(view).length
-               var news = collect_intro_mproperties(view).length
-               var locs = collect_local_mproperties(view).length
+       private fun is_extender(filter: ModelFilter): Bool do
+               var rdfs = collect_redef_mproperties(filter).length
+               var news = collect_intro_mproperties(filter).length
+               var locs = collect_local_mproperties(filter).length
                if news > rdfs and locs > 0 then return true
                return false
        end
 
        # pure specializers always call to super in its redefinitions
-       private fun is_pure_specializer(view: ModelView): Bool do
-               var ovrs = overriden_mproperties(view).length
-               var rdfs = collect_redef_mproperties(view).length
+       private fun is_pure_specializer(filter: ModelFilter): Bool do
+               var ovrs = overriden_mproperties(filter).length
+               var rdfs = collect_redef_mproperties(filter).length
                if ovrs == 0 and rdfs > 0 then return true
                return false
        end
 
        # specializers have more redefinitions that call super than not calling it
-       private fun is_specializer(view: ModelView): Bool do
-               var spcs = extended_mproperties(view).length
-               var ovrs = overriden_mproperties(view).length
-               var rdfs = collect_redef_mproperties(view).length
+       private fun is_specializer(filter: ModelFilter): Bool do
+               var spcs = extended_mproperties(filter).length
+               var ovrs = overriden_mproperties(filter).length
+               var rdfs = collect_redef_mproperties(filter).length
                if spcs > ovrs and rdfs > 0 then return true
                return false
        end
 
        # pure replacers never call to super in its redefinitions
-       private fun is_pure_replacer(view: ModelView): Bool do
-               var spcs = extended_mproperties(view).length
-               var rdfs = collect_redef_mproperties(view).length
+       private fun is_pure_replacer(filter: ModelFilter): Bool do
+               var spcs = extended_mproperties(filter).length
+               var rdfs = collect_redef_mproperties(filter).length
                if spcs == 0 and rdfs > 0 then return true
                return false
        end
 
        # replacers have less redefinitions that call super than not calling it
-       private fun is_replacer(view: ModelView): Bool do
-               var spcs = extended_mproperties(view).length
-               var ovrs = overriden_mproperties(view).length
-               var rdfs = collect_redef_mproperties(view).length
+       private fun is_replacer(filter: ModelFilter): Bool do
+               var spcs = extended_mproperties(filter).length
+               var ovrs = overriden_mproperties(filter).length
+               var rdfs = collect_redef_mproperties(filter).length
                if ovrs > spcs and rdfs > 0 then return true
                return false
        end
 
        # equals contain as redifinition than introduction
-       private fun is_equal(view: ModelView): Bool do
-               var spcs = extended_mproperties(view).length
-               var ovrs = overriden_mproperties(view).length
-               var rdfs = collect_redef_mproperties(view).length
+       private fun is_equal(filter: ModelFilter): Bool do
+               var spcs = extended_mproperties(filter).length
+               var ovrs = overriden_mproperties(filter).length
+               var rdfs = collect_redef_mproperties(filter).length
                if spcs == ovrs and rdfs > 0 then return true
                return false
        end
index 73333a0..bb0612f 100644 (file)
@@ -21,9 +21,9 @@ import nitsmell_toolcontext
 import mclassdef_collect
 
 
-fun call_analyze_methods(mclassdef: MClassDef, model_builder: ModelBuilder, view: ModelView): Array[MMethodDef] do
+fun call_analyze_methods(mclassdef: MClassDef, model_builder: ModelBuilder, filter: ModelFilter): Array[MMethodDef] do
        var mmethoddefs = new Array[MMethodDef]
-       for m_prop in mclassdef.collect_intro_and_redef_mpropdefs(view) do
+       for m_prop in mclassdef.collect_intro_and_redef_mpropdefs(filter) do
                var n_prop = model_builder.mpropdef2node(m_prop)
                #Check if the property is a method definition
                if n_prop isa AMethPropdef and m_prop isa MMethodDef then
index 3a6227f..b740912 100644 (file)
@@ -37,21 +37,20 @@ private class MModulesMetricsPhase
                out.mkdir
 
                var model = toolcontext.modelbuilder.model
-               var model_view = new ModelView(model, mainmodule)
 
                print toolcontext.format_h1("\n# MModules metrics")
 
                var metrics = new MetricSet
-               metrics.register(new MNOA(model_view))
-               metrics.register(new MNOP(model_view))
-               metrics.register(new MNOC(model_view))
-               metrics.register(new MNOD(model_view))
-               metrics.register(new MDIT(model_view))
-               metrics.register(new MNBI(model_view))
-               metrics.register(new MNBR(model_view))
-               metrics.register(new MNBCC(model_view))
-               metrics.register(new MNBAC(model_view))
-               metrics.register(new MNBIC(model_view))
+               metrics.register(new MNOA(model, mainmodule))
+               metrics.register(new MNOP(model, mainmodule))
+               metrics.register(new MNOC(model, mainmodule))
+               metrics.register(new MNOD(model, mainmodule))
+               metrics.register(new MDIT(model, mainmodule))
+               metrics.register(new MNBI(model, mainmodule))
+               metrics.register(new MNBR(model, mainmodule))
+               metrics.register(new MNBCC(model, mainmodule))
+               metrics.register(new MNBAC(model, mainmodule))
+               metrics.register(new MNBIC(model, mainmodule))
 
                var mmodules = new HashSet[MModule]
                for mpackage in model.mpackages do
@@ -86,7 +85,13 @@ abstract class MModuleMetric
        redef type ELM: MModule
 
        # Model view used to collect and filter entities
-       var model_view: ModelView
+       var model: Model
+
+       # Mainmodule used for linearization
+       var mainmodule: MModule
+
+       # Filter to apply on model if any
+       var filter: nullable ModelFilter
 end
 
 # Module Metric: Number of Ancestors
@@ -171,7 +176,7 @@ class MNBD
        redef fun collect(mmodules) do
                for mmodule in mmodules do
                        values[mmodule] = 0
-                       for a in mmodule.collect_ancestors(model_view) do
+                       for a in mmodule.collect_ancestors(mainmodule, filter) do
                                values[mmodule] += a.intro_mclasses.length
                        end
                end
index a7634f1..0cae25d 100644 (file)
@@ -41,11 +41,10 @@ private class NullablesMetricsPhase
 
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(private_visibility)
-               var model_view = new ModelView(model, mainmodule, filter)
 
                var metrics = new MetricSet
-               metrics.register(new CNBA(model_view))
-               metrics.register(new CNBNA(model_view))
+               metrics.register(new CNBA(model, mainmodule, filter))
+               metrics.register(new CNBNA(model, mainmodule, filter))
 
                var mclasses = new HashSet[MClass]
                for mpackage in model.mpackages do
@@ -89,7 +88,7 @@ class CNBNA
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       var all = mclass.collect_accessible_mattributes(model_view)
+                       var all = mclass.collect_accessible_mattributes(mainmodule, filter)
                        for mattr in all do
                                if mattr.is_nullable then values.inc(mclass)
                        end
index 94a4dca..dc3077e 100644 (file)
@@ -39,25 +39,24 @@ private class RTAMetricsPhase
 
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(min_visibility = protected_visibility)
-               var model_view = new ModelView(model, mainmodule, filter)
 
                print toolcontext.format_h1("\n# RTA metrics")
 
                print toolcontext.format_h2("\n ## Live instances by mainmodules")
                var mmetrics = new MetricSet
-               mmetrics.register(new MNLC(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNLT(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNCT(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNLI(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNLM(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNLMD(model_view, toolcontext.modelbuilder))
-               mmetrics.register(new MNLDD(model_view, toolcontext.modelbuilder))
+               mmetrics.register(new MNLC(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLT(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNCT(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLI(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLM(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLMD(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLDD(model, mainmodule, filter, toolcontext.modelbuilder))
                mmetrics.collect(new HashSet[MModule].from([mainmodule]))
                mmetrics.to_console(1, not toolcontext.opt_nocolors.value)
                if csv then mmetrics.to_csv.write_to_file("{out}/{mainmodule}.csv")
 
                var mtypes = new HashSet[MType]
-               var analysis = new MetricsRapidTypeAnalysis(toolcontext.modelbuilder, mainmodule, model_view)
+               var analysis = new MetricsRapidTypeAnalysis(toolcontext.modelbuilder, mainmodule)
                analysis.run_analysis
                mtypes.add_all(analysis.live_types)
                mtypes.add_all(analysis.live_cast_types)
@@ -140,7 +139,7 @@ class MNLI
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.tnli.sum
                end
@@ -156,7 +155,7 @@ class MNLT
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_types.length
                end
@@ -172,7 +171,7 @@ class MNCT
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_cast_types.length
                end
@@ -189,7 +188,7 @@ class MNLC
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
                        var live = new HashSet[MClass]
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        for mtype in analysis.live_types do
                                live.add(mtype.mclass)
@@ -208,7 +207,7 @@ class MNLM
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_methods.length
                end
@@ -224,7 +223,7 @@ class MNLMD
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_methoddefs.length
                end
@@ -241,7 +240,7 @@ class MNLDD
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
                        var dead = 0
-                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule, model_view)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        for mmethod in analysis.live_methods do
                                for mdef in mmethod.mpropdefs do
@@ -356,14 +355,11 @@ end
 class MetricsRapidTypeAnalysis
        super RapidTypeAnalysis
 
-       # Model view used to linearize classes
-       var view: ModelView
-
        # Class Live Instances
-       var cnli: CNLI is lazy do return new CNLI(view)
+       var cnli: CNLI is lazy do return new CNLI(modelbuilder.model, mainmodule)
 
        # Class Live Casts
-       var cnlc: CNLC is lazy do return new CNLC(view)
+       var cnlc: CNLC is lazy do return new CNLC(modelbuilder.model, mainmodule)
 
        # Type Live Instances
        var tnli = new TNLI
index 261fafe..52a6b7a 100644 (file)
@@ -31,6 +31,19 @@ class MDoc
 
        # The original location of the doc for error messages
        var location: Location
+
+       # The comment first line
+       var synopsis: String is lazy do return content.first
+
+       # All comment lines except for the synopsis
+       var comment: String is lazy do
+               var lines = content.to_a
+               if not lines.is_empty then lines.shift
+               return lines.join("\n")
+       end
+
+       # Full comment
+       var documentation: String is lazy do return content.join("\n")
 end
 
 redef class MEntity
index 4df13c6..1943bad 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Collect things from a `ModelView`
+# Collect things from the model.
 #
 # This module introduce several usefull methods to list and count things from a
-# ModelView.
+# Model.
 #
-# First setup you view from a Model:
-#
-# ~~~nitih
-# var view = new ModelView(model, mainmodule)
+# ~~~nitish
+# print number of parents for `{my_class}`
+# print my_class.collect_parents.count
 # ~~~
 #
-# Then ask question using the view:
-#
+# Collect methods can also be used with a ModelFilter:
 # ~~~nitish
-# print number of parents for `{my_class}`
-# print my_class.collect_parents(view).count
+# var filter = new ModelFilter(min_visibility = private_visibility)
+# print my_class.collect_parents(filter).count
 # ~~~
 #
 # **Warning**
 #
-# `model_collect` offers a flattened view of the model without considering any
+# `model_collect` offers a flattened filter of the model without considering any
 # main module.
 # For this reason, `model_collect` lists all the definitions reachable from all
 # modules.
 #
-# This is usefull for tools that need a global view of a model like `nitdoc`,
+# This is usefull for tools that need a global filter of a model like `nitdoc`,
 # `nitx`, `nitmetrics` or `nituml`.
 # It should not be used for compiling stuffs like computing VFT, where the listed
 # entities could not be reachable depending on the modules really imported.
 module model_collect
 
-import model_views
+import model_filters
 
 redef class MEntity
 
@@ -63,16 +61,16 @@ redef class MEntity
        # Collect `self` ancestors (direct and indirect)
        #
        # The concept of ancestor is abstract at this stage.
-       fun collect_ancestors(view: ModelView): Set[MENTITY] do
+       fun collect_ancestors(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] do
                var done = new HashSet[MENTITY]
                var todo = new Array[MENTITY]
 
-               todo.add_all collect_parents(view)
+               todo.add_all collect_parents(mainmodule, filter)
                while todo.not_empty do
                        var mentity = todo.pop
                        if mentity == self or done.has(mentity) then continue
                        done.add mentity
-                       todo.add_all mentity.collect_parents(view)
+                       todo.add_all mentity.collect_parents(mainmodule, filter)
                end
                return done
        end
@@ -80,26 +78,26 @@ redef class MEntity
        # Collect `self` parents (direct ancestors)
        #
        # The concept of parent is abstract at this stage.
-       fun collect_parents(view: ModelView): Set[MENTITY] is abstract
+       fun collect_parents(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] is abstract
 
        # Collect `self` children (direct descendants)
        #
        # The concept of child is abstract at this stage.
-       fun collect_children(view: ModelView): Set[MENTITY] is abstract
+       fun collect_children(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] is abstract
 
        # Collect `self` descendants (direct and direct)
        #
        # The concept of descendant is abstract at this stage.
-       fun collect_descendants(view: ModelView): Set[MENTITY] do
+       fun collect_descendants(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] do
                var done = new HashSet[MENTITY]
                var todo = new Array[MENTITY]
 
-               todo.add_all collect_children(view)
+               todo.add_all collect_children(mainmodule, filter)
                while todo.not_empty do
                        var mentity = todo.pop
                        if mentity == self or done.has(mentity) then continue
                        done.add mentity
-                       todo.add_all mentity.collect_children(view)
+                       todo.add_all mentity.collect_children(mainmodule, filter)
                end
                return done
        end
@@ -116,7 +114,7 @@ redef class MEntity
        # * `MClassDef`: classdef inheritance
        # * `MProperty`: property definitions graph (all propdefs flattened)
        # * `MPropDef`: property definitions graph
-       fun hierarchy_poset(view: ModelView): POSet[MENTITY] do
+       fun hierarchy_poset(mainmodule: MModule, filter: nullable ModelFilter): POSet[MENTITY] do
                var poset = new POSet[MENTITY]
                var parents_done = new HashSet[MENTITY]
                var parents = new Array[MENTITY]
@@ -126,7 +124,7 @@ redef class MEntity
                        if parents_done.has(mentity) then continue
                        parents_done.add mentity
                        poset.add_node mentity
-                       for parent in mentity.collect_parents(view) do
+                       for parent in mentity.collect_parents(mainmodule, filter) do
                                poset.add_edge(mentity, parent)
                                parents.add parent
                        end
@@ -138,7 +136,7 @@ redef class MEntity
                        var mentity = children.pop
                        if children_done.has(mentity) then continue
                        children_done.add mentity
-                       for child in mentity.collect_children(view) do
+                       for child in mentity.collect_children(mainmodule, filter) do
                                poset.add_edge(child, mentity)
                                children.add child
                        end
@@ -150,38 +148,116 @@ end
 redef class Model
 
        # Collect all MPackages in `self`
-       fun collect_mpackages(view: ModelView): HashSet[MPackage] do
+       fun collect_mpackages(filter: nullable ModelFilter): HashSet[MPackage] do
                var res = new HashSet[MPackage]
                for mpackage in mpackages do
-                       if not view.accept_mentity(mpackage) then continue
-                       res.add(mpackage)
+                       if filter == null or filter.accept_mentity(mpackage) then res.add(mpackage)
+               end
+               return res
+       end
+
+       # Collect all MGroups in `self`
+       fun collect_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do
+               var res = new HashSet[MGroup]
+               for mpackage in collect_mpackages(filter) do
+                       res.add_all mpackage.collect_all_mgroups(filter)
                end
                return res
        end
 
        # Collect all MModules in `self`
-       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+       fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do
                var res = new HashSet[MModule]
-               for mpackage in collect_mpackages(view) do
-                       res.add_all mpackage.collect_all_mmodules(view)
+               for mpackage in collect_mpackages(filter) do
+                       res.add_all mpackage.collect_all_mmodules(filter)
+               end
+               return res
+       end
+
+       # Collect all MClasses in `self`
+       fun collect_mclasses(filter: nullable ModelFilter): HashSet[MClass] do
+               var res = new HashSet[MClass]
+               for mclass in mclasses do
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
                end
                return res
        end
 
        # Collect all MClasses introduced in `self`
-       fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+       fun collect_intro_mclasses(filter: nullable ModelFilter): HashSet[MClass] do
                var res = new HashSet[MClass]
-               for mpackage in collect_mpackages(view) do
-                       res.add_all mpackage.collect_intro_mclasses(view)
+               for mpackage in collect_mpackages(filter) do
+                       res.add_all mpackage.collect_intro_mclasses(filter)
+               end
+               return res
+       end
+
+       # Collect all MClassDefs in `self`
+       fun collect_mclassdefs(filter: nullable ModelFilter): HashSet[MClassDef] do
+               var res = new HashSet[MClassDef]
+               for mclass in collect_mclasses(filter) do
+                       res.add_all mclass.collect_mclassdefs(filter)
                end
                return res
        end
 
        # Collect all MProperties introduced in `self`
-       fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+       fun collect_intro_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do
+               var res = new HashSet[MProperty]
+               for mpackage in collect_mpackages(filter) do
+                       res.add_all mpackage.collect_intro_mproperties(filter)
+               end
+               return res
+       end
+
+       # Collect all MProperties in `self`
+       fun collect_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do
                var res = new HashSet[MProperty]
-               for mpackage in collect_mpackages(view) do
-                       res.add_all mpackage.collect_intro_mproperties(view)
+               for mproperty in mproperties do
+                       if filter == null or filter.accept_mentity(mproperty) then res.add mproperty
+               end
+               return res
+       end
+
+       # Collect all MPropDefs in `self`
+       fun collect_mpropdefs(filter: nullable ModelFilter): HashSet[MPropDef] do
+               var res = new HashSet[MPropDef]
+               for mproperty in collect_mproperties(filter) do
+                       for mpropdef in mproperty.mpropdefs do
+                               if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef
+                       end
+               end
+               return res
+       end
+
+       # Collect all MEntities in `self`
+       fun collect_mentities(filter: nullable ModelFilter): HashSet[MEntity] do
+               var res = new HashSet[MEntity]
+               res.add_all collect_mpackages(filter)
+               res.add_all collect_mgroups(filter)
+               res.add_all collect_mmodules(filter)
+               res.add_all collect_mclasses(filter)
+               res.add_all collect_mclassdefs(filter)
+               res.add_all collect_mproperties(filter)
+               res.add_all collect_mpropdefs(filter)
+               return res
+       end
+
+       # Searches the MEntity that matches `full_name`.
+       fun mentity_by_full_name(full_name: String, filter: nullable ModelFilter): nullable MEntity do
+               for mentity in collect_mentities(filter) do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
+                       if mentity.full_name == full_name then return mentity
+               end
+               return null
+       end
+
+       # Searches the MEntities that matches `full_name`.
+       fun mentities_by_name(name: String, filter: nullable ModelFilter): Array[MEntity] do
+               var res = new Array[MEntity]
+               for mentity in collect_mentities(filter) do
+                       if filter != null and not filter.accept_mentity(mentity) then continue
+                       if mentity.name == name then res.add mentity
                end
                return res
        end
@@ -192,125 +268,124 @@ redef class MPackage
        redef fun collect_modifiers do return super + ["package"]
 
        # Collect all packages directly imported by `self`
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mgroup in mgroups do
-                       for parent in mgroup.collect_parents(view) do
+                       for parent in mgroup.collect_parents(mainmodule, filter) do
                                var mpackage = parent.mpackage
-                               if mpackage == self or not view.accept_mentity(mpackage) then continue
-                               res.add(mpackage)
+                               if mpackage == self then continue
+                               if filter == null or filter.accept_mentity(mpackage) then res.add(mpackage)
                        end
                end
                return res
        end
 
        # Collect all packages that directly depends on `self`
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
-               for mpackage in view.mpackages do
-                       if mpackage.collect_parents(view).has(self) then res.add mpackage
+               for mpackage in model.collect_mpackages(filter) do
+                       if mpackage.collect_parents(mainmodule, filter).has(self) then res.add mpackage
                end
                return res
        end
 
        # Collect all groups contained in `self`
-       fun collect_all_mgroups(view: ModelView): HashSet[MGroup] do
+       fun collect_all_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do
                var res = new HashSet[MGroup]
                for mgroup in mgroups do
-                       if not view.accept_mentity(mgroup) then continue
-                       res.add(mgroup)
+                       if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup)
                end
                return res
        end
 
        # Collect only groups contained in `self.root`
-       fun collect_mgroups(view: ModelView): HashSet[MGroup] do
+       fun collect_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do
                var res = new HashSet[MGroup]
                var root = self.root
                if root == null then return res
-               res.add_all root.collect_mgroups(view)
+               res.add_all root.collect_mgroups(filter)
                return res
        end
 
        # Collect all modules contained in `self`
-       fun collect_all_mmodules(view: ModelView): HashSet[MModule] do
+       fun collect_all_mmodules(filter: nullable ModelFilter): HashSet[MModule] do
                var res = new HashSet[MModule]
-               for mgroup in collect_all_mgroups(view) do
-                       res.add_all mgroup.collect_mmodules(view)
+               for mgroup in collect_all_mgroups(filter) do
+                       res.add_all mgroup.collect_mmodules(filter)
                end
                return res
        end
 
        # Collect only modules contained in `self.root`
-       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+       fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do
                var res = new HashSet[MModule]
                var root = self.root
                if root == null then return res
-               res.add_all root.collect_mmodules(view)
+               res.add_all root.collect_mmodules(filter)
                return res
        end
 
        # Collect all classes introduced in `self`
-       fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+       fun collect_intro_mclasses(filter: nullable ModelFilter): HashSet[MClass] do
                var res = new HashSet[MClass]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_mclasses(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_mclasses(filter)
                        end
                end
                return res
        end
 
        # Collect all classes redefined or refined in `self`
-       fun collect_redef_mclasses(view: ModelView): Set[MClass] do
+       fun collect_redef_mclasses(filter: nullable ModelFilter): Set[MClass] do
                var res = new HashSet[MClass]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_redef_mclasses(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_redef_mclasses(filter)
                        end
                end
                return res
        end
 
        # Collect all properties introduced in `self`
-       fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+       fun collect_intro_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do
                var res = new HashSet[MProperty]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_mproperties(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_mproperties(filter)
                        end
                end
                return res
        end
 
        # Collect all properties redefined in `self`
-       fun collect_redef_mproperties(view: ModelView): HashSet[MProperty] do
+       fun collect_redef_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do
                var res = new HashSet[MProperty]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_redef_mproperties(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_redef_mproperties(filter)
                        end
                end
                return res
        end
 
        # Collect all attributes introduced in `self`
-       fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+       fun collect_intro_attributes(filter: nullable ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_attributes(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_attributes(filter)
                        end
                end
                return res
        end
 
        # Collect all inits introduced in `self`
-       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+       fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_inits(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_inits(filter)
                        end
                end
                return res
@@ -319,22 +394,22 @@ redef class MPackage
        # Collect all methods introduced in `self` excluding inits
        #
        # See `collect_intro_inits`.
-       fun collect_intro_methods(view: ModelView): Set[MMethod] do
+       fun collect_intro_methods(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_methods(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_methods(filter)
                        end
                end
                return res
        end
 
        # Collect all virtual types introduced in `self`
-       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_intro_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var res = new HashSet[MVirtualTypeProp]
                for mgroup in mgroups do
-                       for mmodule in collect_all_mmodules(view) do
-                               res.add_all mmodule.collect_intro_vts(view)
+                       for mmodule in collect_all_mmodules(filter) do
+                               res.add_all mmodule.collect_intro_vts(filter)
                        end
                end
                return res
@@ -346,54 +421,52 @@ redef class MGroup
        redef fun collect_modifiers do return super + ["group"]
 
        # Collect all groups directly import by `self`
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mmodule in mmodules do
-                       for parent in mmodule.collect_parents(view) do
+                       for parent in mmodule.collect_parents(mainmodule, filter) do
                                var mgroup = parent.mgroup
                                if mgroup == null or mgroup == self then continue
-                               if not view.accept_mentity(mgroup) then continue
-                               res.add(mgroup)
+                               if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup)
                        end
                end
                return res
        end
 
        # Collect all group that directly import `self`
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
-               for mgroup in view.mgroups do
-                       if mgroup == self or not view.accept_mentity(mgroup) then continue
-                       if mgroup.collect_parents(view).has(self) then res.add mgroup
+               for mgroup in model.collect_mgroups(filter) do
+                       if mgroup == self then continue
+                       if filter != null and not filter.accept_mentity(mgroup) then continue
+                       if mgroup.collect_parents(mainmodule, filter).has(self) then res.add mgroup
                end
                return res
        end
 
        # Collect all groups contained in `self`
-       fun collect_mgroups(view: ModelView): HashSet[MENTITY] do
+       fun collect_mgroups(filter: nullable ModelFilter): HashSet[MENTITY] do
                var res = new HashSet[MENTITY]
                for mgroup in in_nesting.direct_smallers do
-                       if not view.accept_mentity(mgroup) then continue
-                       res.add(mgroup)
+                       if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup)
                end
                return res
        end
 
        # Collect all modules contained in `self`
-       fun collect_all_mmodules(view: ModelView): HashSet[MModule] do
+       fun collect_all_mmodules(filter: nullable ModelFilter): HashSet[MModule] do
                var res = new HashSet[MModule]
-               for mgroup in collect_mgroups(view) do
-                       res.add_all mgroup.collect_all_mmodules(view)
+               for mgroup in collect_mgroups(filter) do
+                       res.add_all mgroup.collect_all_mmodules(filter)
                end
                return res
        end
 
        # Collect all modules contained in `self`
-       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+       fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do
                var res = new HashSet[MModule]
                for mmodule in mmodules do
-                       if not view.accept_mentity(mmodule) then continue
-                       res.add(mmodule)
+                       if filter == null or filter.accept_mentity(mmodule) then res.add(mmodule)
                end
                return res
        end
@@ -404,121 +477,125 @@ redef class MModule
        redef fun collect_modifiers do return super + ["module"]
 
        # Collect all modules directly imported by `self`
-       redef fun collect_parents(view) do
+       redef fun collect_ancestors(mainmodule, filter) do
+               var res = new HashSet[MENTITY]
+               for mentity in in_importation.greaters do
+                       if mentity == self then continue
+                       if filter == null or filter.accept_mentity(mentity) then res.add mentity
+               end
+               return res
+       end
+
+       # Collect all modules directly imported by `self`
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mentity in in_importation.direct_greaters do
                        if mentity == self then continue
-                       if not view.accept_mentity(mentity) then continue
-                       res.add mentity
+                       if filter == null or filter.accept_mentity(mentity) then res.add mentity
                end
                return res
        end
 
        # Collect all modules that directly import `self`
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mentity in in_importation.direct_smallers do
                        if mentity == self then continue
-                       if not view.accept_mentity(mentity) then continue
-                       res.add mentity
+                       if filter == null or filter.accept_mentity(mentity) then res.add mentity
                end
                return res
        end
 
        # Collect all module descendants of `self` (direct and transitive imports)
-       redef fun collect_descendants(view) do
+       redef fun collect_descendants(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mentity in in_importation.smallers do
                        if mentity == self then continue
-                       if not view.accept_mentity(mentity) then continue
-                       res.add mentity
+                       if filter == null or filter.accept_mentity(mentity) then res.add mentity
                end
                return res
        end
 
        # Collect all class definitions introduced in `self`
-       fun collect_intro_mclassdefs(view: ModelView): Set[MClassDef] do
+       fun collect_intro_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do
                var res = new HashSet[MClassDef]
                for mclassdef in mclassdefs do
                        if not mclassdef.is_intro then continue
-                       if not view.accept_mentity(mclassdef) then continue
-                       res.add mclassdef
+                       if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef
                end
                return res
        end
 
        # Collect all class definitions refined in `self`
-       fun collect_redef_mclassdefs(view: ModelView): Set[MClassDef] do
+       fun collect_redef_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do
                var res = new HashSet[MClassDef]
                for mclassdef in mclassdefs do
                        if mclassdef.is_intro then continue
-                       if not view.accept_mentity(mclassdef) then continue
-                       res.add mclassdef
+                       if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef
                end
                return res
        end
 
        # Collect all class definitions introduced and refined in `self`
-       fun collect_local_mclassdefs(view: ModelView): Set[MClassDef] do
+       fun collect_local_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do
                var res = new HashSet[MClassDef]
-               res.add_all collect_intro_mclassdefs(view)
-               res.add_all collect_redef_mclassdefs(view)
+               res.add_all collect_intro_mclassdefs(filter)
+               res.add_all collect_redef_mclassdefs(filter)
                return res
        end
 
        # Collect all classes introduced in `self`
-       fun collect_intro_mclasses(view: ModelView): Set[MClass] do
+       fun collect_intro_mclasses(filter: nullable ModelFilter): Set[MClass] do
                var res = new HashSet[MClass]
                for mclass in intro_mclasses do
-                       if not view.accept_mentity(mclass) then continue
-                       res.add mclass
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
                end
                return res
        end
 
        # Collect all classes refined in `self`
-       fun collect_redef_mclasses(view: ModelView): Set[MClass] do
+       fun collect_redef_mclasses(filter: nullable ModelFilter): Set[MClass] do
                var mclasses = new HashSet[MClass]
                for mclassdef in mclassdefs do
-                       if not view.accept_mentity(mclassdef.mclass) then continue
+                       if filter != null and not filter.accept_mentity(mclassdef.mclass) then continue
                        if not mclassdef.is_intro then mclasses.add(mclassdef.mclass)
                end
                return mclasses
        end
 
        # Collect all classes introduced and refined in `self`
-       fun collect_local_mclasses(view: ModelView): Set[MClass] do
+       fun collect_local_mclasses(filter: nullable ModelFilter): Set[MClass] do
                var res = new HashSet[MClass]
-               res.add_all collect_intro_mclasses(view)
-               res.add_all collect_redef_mclasses(view)
+               res.add_all collect_intro_mclasses(filter)
+               res.add_all collect_redef_mclasses(filter)
                return res
        end
 
        # Collect all classes imported from `self` parents
-       fun collect_imported_mclasses(view: ModelView): Set[MClass] do
+       fun collect_imported_mclasses(mainmodule: MModule, filter: nullable ModelFilter): Set[MClass] do
                var res = new HashSet[MClass]
-               for parent in collect_parents(view) do
-                       res.add_all parent.collect_intro_mclasses(view)
-                       res.add_all parent.collect_redef_mclasses(view)
-                       res.add_all parent.collect_imported_mclasses(view)
+               for parent in collect_parents(mainmodule, filter) do
+                       res.add_all parent.collect_intro_mclasses(filter)
+                       res.add_all parent.collect_redef_mclasses(filter)
+                       res.add_all parent.collect_imported_mclasses(mainmodule, filter)
                end
                return res
        end
 
        # Collect all properties introduced in `self`
-       fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_intro_mproperties(filter: nullable ModelFilter): Set[MProperty] do
                var res = new HashSet[MProperty]
-               for mclass in collect_intro_mclasses(view) do
-                       res.add_all mclass.collect_intro_mproperties(view)
+               for mclass in collect_intro_mclasses(filter) do
+                       res.add_all mclass.collect_intro_mproperties(filter)
                end
                return res
        end
 
        # Collect properties redefined in `self`
-       fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_redef_mproperties(filter: nullable ModelFilter): Set[MProperty] do
                var res = new HashSet[MProperty]
                for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.collect_redef_mpropdefs(view) do
+                       for mpropdef in mclassdef.collect_redef_mpropdefs(filter) do
                                res.add mpropdef.mproperty
                        end
                end
@@ -526,36 +603,36 @@ redef class MModule
        end
 
        # Collect attributes introduced in `self`
-       fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+       fun collect_intro_attributes(filter: nullable ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect all inits introduced in `self`
-       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+       fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MMethod and mproperty.is_init then res.add(mproperty)
                end
                return res
        end
 
        # Collect methods introduced in `self` (without inits)
-       fun collect_intro_methods(view: ModelView): Set[MMethod] do
+       fun collect_intro_methods(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MMethod and not mproperty.is_init then res.add(mproperty)
                end
                return res
        end
 
        # Collect virtual types introduced in `self`
-       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_intro_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var res = new HashSet[MVirtualTypeProp]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MVirtualTypeProp then res.add(mproperty)
                end
                return res
@@ -572,107 +649,122 @@ redef class MClass
                return mclassdefs
        end
 
+       # Collect all ancestors of `self`
+       redef fun collect_ancestors(mainmodule, filter) do
+               var res = new HashSet[MENTITY]
+               if not mainmodule.flatten_mclass_hierarchy.has(self) then return res
+               for mclass in in_hierarchy(mainmodule).greaters do
+                       if mclass == self then continue
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
+               end
+               return res
+       end
+
        # Collect all direct parents of `self`
-       #
-       # This method uses a flattened hierarchy containing all the mclassdefs.
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
-               if not view.mainmodule.flatten_mclass_hierarchy.has(self) then return res
-               for mclass in in_hierarchy(view.mainmodule).direct_greaters do
-                       if mclass == self or not view.accept_mentity(mclass) then continue
-                       res.add mclass
+               if not mainmodule.flatten_mclass_hierarchy.has(self) then return res
+               for mclass in in_hierarchy(mainmodule).direct_greaters do
+                       if mclass == self then continue
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
                end
                return res
        end
 
        # Collect all direct children of `self`
-       #
-       # This method uses a flattened hierarchy containing all the mclassdefs.
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
+               var res = new HashSet[MENTITY]
+               if not mainmodule.flatten_mclass_hierarchy.has(self) then return res
+               for mclass in in_hierarchy(mainmodule).direct_smallers do
+                       if mclass == self then continue
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
+               end
+               return res
+       end
+
+       # Collect all descendants of `self`
+       redef fun collect_descendants(mainmodule, filter) do
                var res = new HashSet[MENTITY]
-               if not view.mainmodule.flatten_mclass_hierarchy.has(self) then return res
-               for mclass in in_hierarchy(view.mainmodule).direct_smallers do
-                       if mclass == self or not view.accept_mentity(mclass) then continue
-                       res.add mclass
+               if not mainmodule.flatten_mclass_hierarchy.has(self) then return res
+               for mclass in in_hierarchy(mainmodule).smallers do
+                       if mclass == self then continue
+                       if filter == null or filter.accept_mentity(mclass) then res.add mclass
                end
                return res
        end
 
        # Collect all class definitions of `self`
-       fun collect_mclassdefs(view: ModelView): Set[MClassDef] do
+       fun collect_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do
                var res = new HashSet[MClassDef]
                for mclassdef in mclassdefs do
-                       if not view.accept_mentity(mclassdef) then continue
-                       res.add mclassdef
+                       if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef
                end
                return res
        end
 
        # Collect all property definitions that are introductions in `self`
-       fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_intro_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var set = new HashSet[MPropDef]
                for mclassdef in mclassdefs do
                        for mpropdef in mclassdef.mpropdefs do
                                if not mpropdef.is_intro then continue
-                               if not view.accept_mentity(mpropdef) then continue
-                               set.add(mpropdef)
+                               if filter == null or filter.accept_mentity(mpropdef) then set.add(mpropdef)
                        end
                end
                return set
        end
 
        # Collect all properties introduced in `self`
-       fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_intro_mproperties(filter: nullable ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                for mclassdef in mclassdefs do
                        for mprop in mclassdef.intro_mproperties do
-                               if not view.accept_mentity(mprop) then continue
-                               set.add(mprop)
+                               if filter == null or filter.accept_mentity(mprop) then set.add(mprop)
                        end
                end
                return set
        end
 
        # Collect all propierty definitions that are redefinition in `self`
-       fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_redef_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var set = new HashSet[MPropDef]
                for mclassdef in mclassdefs do
                        for mpropdef in mclassdef.mpropdefs do
                                if mpropdef.is_intro then continue
-                               if not view.accept_mentity(mpropdef) then continue
-                               set.add(mpropdef)
+                               if filter == null or filter.accept_mentity(mpropdef) then set.add(mpropdef)
                        end
                end
                return set
        end
 
        # Collect all properties redefined in `self`
-       fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_redef_mproperties(filter: nullable ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
                for mclassdef in mclassdefs do
                        for mpropdef in mclassdef.mpropdefs do
                                if mpropdef.mproperty.intro_mclassdef.mclass == self then continue
-                               if not view.accept_mentity(mpropdef) then continue
-                               set.add(mpropdef.mproperty)
+                               if filter == null or filter.accept_mentity(mpropdef) then
+                                       set.add(mpropdef.mproperty)
+                               end
                        end
                end
                return set
        end
 
        # Collect all properties introduced and redefined in `self`
-       fun collect_local_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_local_mproperties(filter: nullable ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
-               set.add_all collect_intro_mproperties(view)
-               set.add_all collect_redef_mproperties(view)
+               set.add_all collect_intro_mproperties(filter)
+               set.add_all collect_redef_mproperties(filter)
                return set
        end
 
        # Collect all properties inehrited by `self`
-       fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_inherited_mproperties(mainmodule: MModule, filter: nullable ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
-               for parent in collect_parents(view) do
-                       set.add_all(parent.collect_intro_mproperties(view))
-                       set.add_all(parent.collect_inherited_mproperties(view))
+               for parent in collect_parents(mainmodule, filter) do
+                       set.add_all(parent.collect_intro_mproperties(filter))
+                       set.add_all(parent.collect_inherited_mproperties(mainmodule, filter))
                end
                return set
        end
@@ -680,44 +772,44 @@ redef class MClass
        # Collect all properties accessible by `self`
        #
        # This include introduced, redefined, inherited properties.
-       fun collect_accessible_mproperties(view: ModelView): Set[MProperty] do
+       fun collect_accessible_mproperties(mainmodule: MModule, filter: nullable ModelFilter): Set[MProperty] do
                var set = new HashSet[MProperty]
-               set.add_all(collect_intro_mproperties(view))
-               set.add_all(collect_redef_mproperties(view))
-               set.add_all(collect_inherited_mproperties(view))
+               set.add_all(collect_intro_mproperties(filter))
+               set.add_all(collect_redef_mproperties(filter))
+               set.add_all(collect_inherited_mproperties(mainmodule, filter))
                return set
        end
 
        # Collect all methods introduced in `self`
-       fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_intro_mmethods(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
        end
 
        # Collect all methods redefined in `self`
-       fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_redef_mmethods(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_redef_mproperties(view) do
+               for mproperty in collect_redef_mproperties(filter) do
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
        end
 
        # Collect all methods introduced and redefined in `self`
-       fun collect_local_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_local_mmethods(filter: nullable ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all collect_intro_mmethods(view)
-               set.add_all collect_redef_mmethods(view)
+               set.add_all collect_intro_mmethods(filter)
+               set.add_all collect_redef_mmethods(filter)
                return set
        end
 
        # Collect all methods inherited by `self`
-       fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_inherited_mmethods(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_inherited_mproperties(view) do
+               for mproperty in collect_inherited_mproperties(mainmodule, filter) do
                        if mproperty isa MMethod then res.add(mproperty)
                end
                return res
@@ -726,44 +818,44 @@ redef class MClass
        # Collect all methods accessible by `self`
        #
        # This include introduced, redefined, inherited methods.
-       fun collect_accessible_mmethods(view: ModelView): Set[MMethod] do
+       fun collect_accessible_mmethods(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all(collect_intro_mmethods(view))
-               set.add_all(collect_redef_mmethods(view))
-               set.add_all(collect_inherited_mmethods(view))
+               set.add_all(collect_intro_mmethods(filter))
+               set.add_all(collect_redef_mmethods(filter))
+               set.add_all(collect_inherited_mmethods(mainmodule, filter))
                return set
        end
 
        # Collect all attributes introduced in `self`
-       fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_intro_mattributes(filter: nullable ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect all attributes redefined in `self`
-       fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_redef_mattributes(filter: nullable ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_redef_mproperties(view) do
+               for mproperty in collect_redef_mproperties(filter) do
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
        # Collect all attributes introduced and redefined in `self`
-       fun collect_local_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_local_mattributes(filter: nullable ModelFilter): Set[MAttribute] do
                var set = new HashSet[MAttribute]
-               set.add_all collect_intro_mattributes(view)
-               set.add_all collect_redef_mattributes(view)
+               set.add_all collect_intro_mattributes(filter)
+               set.add_all collect_redef_mattributes(filter)
                return set
        end
 
        # Collect all attributes inherited by `self`
-       fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_inherited_mattributes(mainmodule: MModule, filter: nullable ModelFilter): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_inherited_mproperties(view) do
+               for mproperty in collect_inherited_mproperties(mainmodule, filter) do
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
@@ -772,44 +864,44 @@ redef class MClass
        # Collect all attributes accessible by `self`
        #
        # This include introduced, redefined, inherited mattributes.
-       fun collect_accessible_mattributes(view: ModelView): Set[MAttribute] do
+       fun collect_accessible_mattributes(mainmodule: MModule, filter: nullable ModelFilter): Set[MAttribute] do
                var set = new HashSet[MAttribute]
-               set.add_all(collect_intro_mattributes(view))
-               set.add_all(collect_redef_mattributes(view))
-               set.add_all(collect_inherited_mattributes(view))
+               set.add_all(collect_intro_mattributes(filter))
+               set.add_all(collect_redef_mattributes(filter))
+               set.add_all(collect_inherited_mattributes(mainmodule, filter))
                return set
        end
 
        # Collect all init methods introduced in `self`
-       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+       fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mmethods(view) do
+               for mproperty in collect_intro_mmethods(filter) do
                        if mproperty.is_init then res.add(mproperty)
                end
                return res
        end
 
        # Collect all init methods redefined in `self`
-       fun collect_redef_inits(view: ModelView): Set[MMethod] do
+       fun collect_redef_inits(filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_redef_mmethods(view) do
+               for mproperty in collect_redef_mmethods(filter) do
                        if mproperty.is_init then res.add(mproperty)
                end
                return res
        end
 
        # Collect all init methods introduced and redefined in `self`
-       fun collect_local_inits(view: ModelView): Set[MMethod] do
+       fun collect_local_inits(filter: nullable ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all collect_intro_inits(view)
-               set.add_all collect_redef_inits(view)
+               set.add_all collect_intro_inits(filter)
+               set.add_all collect_redef_inits(filter)
                return set
        end
 
        # Collect all init methods inherited by `self`
-       fun collect_inherited_inits(view: ModelView): Set[MMethod] do
+       fun collect_inherited_inits(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_inherited_mmethods(view) do
+               for mproperty in collect_inherited_mmethods(mainmodule, filter) do
                        if mproperty.is_init then res.add(mproperty)
                end
                return res
@@ -818,44 +910,44 @@ redef class MClass
        # Collect all init methods accessible by `self`
        #
        # This include introduced, redefined, inherited inits.
-       fun collect_accessible_inits(view: ModelView): Set[MMethod] do
+       fun collect_accessible_inits(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all(collect_intro_inits(view))
-               set.add_all(collect_redef_inits(view))
-               set.add_all(collect_inherited_inits(view))
+               set.add_all(collect_intro_inits(filter))
+               set.add_all(collect_redef_inits(filter))
+               set.add_all(collect_inherited_inits(mainmodule, filter))
                return set
        end
 
        # Collect all virtual types introduced in `self`
-       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_intro_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var res = new HashSet[MVirtualTypeProp]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MVirtualTypeProp then res.add(mproperty)
                end
                return res
        end
 
        # Collect all virtual types redefined in `self`
-       fun collect_redef_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_redef_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var res = new HashSet[MVirtualTypeProp]
-               for mproperty in collect_intro_mproperties(view) do
+               for mproperty in collect_intro_mproperties(filter) do
                        if mproperty isa MVirtualTypeProp then res.add(mproperty)
                end
                return res
        end
 
        # Collect all virtual types introduced or redefined in `self`
-       fun collect_local_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_local_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var set = new HashSet[MVirtualTypeProp]
-               set.add_all collect_intro_vts(view)
-               set.add_all collect_redef_vts(view)
+               set.add_all collect_intro_vts(filter)
+               set.add_all collect_redef_vts(filter)
                return set
        end
 
        # Collect all virtual types inherited by `self`
-       fun collect_inherited_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_inherited_vts(mainmodule: MModule, filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var res = new HashSet[MVirtualTypeProp]
-               for mproperty in collect_inherited_mproperties(view) do
+               for mproperty in collect_inherited_mproperties(mainmodule, filter) do
                        if mproperty isa MVirtualTypeProp then res.add(mproperty)
                end
                return res
@@ -864,9 +956,9 @@ redef class MClass
        # Collect all virtual types accessible by `self`
        #
        # This include introduced, redefined, inherited virtual types.
-       fun collect_accessible_vts(view: ModelView): Set[MVirtualTypeProp] do
+       fun collect_accessible_vts(mainmodule: MModule, filter: nullable ModelFilter): Set[MVirtualTypeProp] do
                var set = new HashSet[MVirtualTypeProp]
-               for mproperty in collect_accessible_mproperties(view) do
+               for mproperty in collect_accessible_mproperties(mainmodule, filter) do
                        if mproperty isa MVirtualTypeProp then set.add mproperty
                end
                return set
@@ -897,42 +989,41 @@ redef class MClassDef
                return mclassdefs
        end
 
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                var hierarchy = self.in_hierarchy
                if hierarchy == null then return res
                for parent in hierarchy.direct_greaters do
-                       if parent == self or not view.accept_mentity(parent) then continue
-                       res.add parent
+                       if parent == self then continue
+                       if filter == null or filter.accept_mentity(parent) then res.add parent
                end
                return res
        end
 
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                var hierarchy = self.in_hierarchy
                if hierarchy == null then return res
                for child in hierarchy.direct_smallers do
-                       if child == self or not view.accept_mentity(child) then continue
-                       res.add child
+                       if child == self then continue
+                       if filter == null or filter.accept_mentity(child) then res.add child
                end
                return res
        end
 
        # Collect all property definitions in `self`
-       fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mpropdef in mpropdefs do
-                       if not view.accept_mentity(mpropdef) then continue
-                       res.add mpropdef
+                       if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef
                end
                return res
        end
 
        # Collect all attribute definitions in `self`
-       fun collect_mattributedefs(view: ModelView): Set[MAttributeDef] do
+       fun collect_mattributedefs(filter: nullable ModelFilter): Set[MAttributeDef] do
                var res = new HashSet[MAttributeDef]
-               for mpropdef in collect_mpropdefs(view) do
+               for mpropdef in collect_mpropdefs(filter) do
                        if not mpropdef isa MAttributeDef then continue
                        res.add mpropdef
                end
@@ -940,9 +1031,9 @@ redef class MClassDef
        end
 
        # Collect all methods definitions in `self`
-       fun collect_mmethoddefs(view: ModelView): Set[MMethodDef] do
+       fun collect_mmethoddefs(filter: nullable ModelFilter): Set[MMethodDef] do
                var res = new HashSet[MMethodDef]
-               for mpropdef in collect_mpropdefs(view) do
+               for mpropdef in collect_mpropdefs(filter) do
                        if not mpropdef isa MMethodDef then continue
                        res.add mpropdef
                end
@@ -950,9 +1041,9 @@ redef class MClassDef
        end
 
        # Collect all virtual types definitions in `self`
-       fun collect_mtypedefs(view: ModelView): Set[MVirtualTypeDef] do
+       fun collect_mtypedefs(filter: nullable ModelFilter): Set[MVirtualTypeDef] do
                var res = new HashSet[MVirtualTypeDef]
-               for mpropdef in collect_mpropdefs(view) do
+               for mpropdef in collect_mpropdefs(filter) do
                        if not mpropdef isa MVirtualTypeDef then continue
                        res.add mpropdef
                end
@@ -960,23 +1051,21 @@ redef class MClassDef
        end
 
        # Collect all property definitions that are introduction in `self`
-       fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_intro_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mpropdef in mpropdefs do
                        if not mpropdef.is_intro then continue
-                       if not view.accept_mentity(mpropdef) then continue
-                       res.add mpropdef
+                       if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef
                end
                return res
        end
 
        # Collect all property definitions that are redefinition in `self`
-       fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_redef_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mpropdef in mpropdefs do
                        if mpropdef.is_intro then continue
-                       if not view.accept_mentity(mpropdef) then continue
-                       res.add mpropdef
+                       if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef
                end
                return res
        end
@@ -992,34 +1081,33 @@ redef class MProperty
        end
 
        # Collect all property definitions of `self`
-       fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
+       fun collect_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mpropdef in mpropdefs do
-                       if not view.accept_mentity(mpropdef) then continue
-                       res.add mpropdef
+                       if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef
                end
                return res
        end
 
        # Collect all direct super definitions of `self`
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mpropdef in mpropdefs do
-                       for parent in mpropdef.collect_parents(view) do
-                               if not view.accept_mentity(parent) then continue
-                               res.add parent.mproperty
+                       for parent in mpropdef.collect_parents(mainmodule, filter) do
+                               var mprop = parent.mproperty
+                               if filter == null or filter.accept_mentity(mprop) then res.add mprop
                        end
                end
                return res
        end
 
        # Collection all definitions that have `self` as a direct super definition
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                for mpropdef in mpropdefs do
-                       for child in mpropdef.collect_parents(view) do
-                               if not view.accept_mentity(child) then continue
-                               res.add child.mproperty
+                       for child in mpropdef.collect_parents(mainmodule, filter) do
+                               var mprop = child.mproperty
+                               if filter == null or filter.accept_mentity(mprop) then res.add mprop
                        end
                end
                return res
@@ -1070,7 +1158,7 @@ redef class MPropDef
        end
 
        # Collect only the next definition of `self`
-       redef fun collect_parents(view) do
+       redef fun collect_parents(mainmodule, filter) do
                var res = new HashSet[MENTITY]
                var mpropdef = self
                while not mpropdef.is_intro do
@@ -1081,10 +1169,10 @@ redef class MPropDef
        end
 
        # Collect all children definitions that directly depend on `self`
-       redef fun collect_children(view) do
+       redef fun collect_children(mainmodule, filter) do
                var res = new HashSet[MENTITY]
-               for mpropdef in mproperty.collect_mpropdefs(view) do
-                       if mpropdef.collect_parents(view).has(self) then res.add mpropdef
+               for mpropdef in mproperty.collect_mpropdefs(filter) do
+                       if mpropdef.collect_parents(mainmodule, filter).has(self) then res.add mpropdef
                end
                return res
        end
index 740a17a..0d47a92 100644 (file)
@@ -15,6 +15,7 @@
 module model_filters
 
 import model_examples
+import parse_annotations
 
 # A list of filters that can be applied on a MEntity
 #
@@ -40,12 +41,30 @@ import model_examples
 # ~~~
 class ModelFilter
 
+       # Initialize `self` by copying the options from another `filter`
+       init from(filter: ModelFilter) do
+               init(
+                       min_visibility = filter.min_visibility,
+                       accept_fictive = filter.accept_fictive,
+                       accept_test = filter.accept_test,
+                       accept_redef = filter.accept_redef,
+                       accept_extern = filter.accept_extern,
+                       accept_example = filter.accept_example,
+                       accept_attribute = filter.accept_attribute,
+                       accept_empty_doc = filter.accept_empty_doc,
+                       accept_inherited = filter.accept_inherited,
+                       accept_full_name = filter.accept_full_name
+               )
+       end
+
        # Accept `mentity` based on all the options from `self`?
        #
        # If one of the filter returns `false` then the `mentity` is not accepted.
        fun accept_mentity(mentity: MEntity): Bool do
+               if not accept_mentity_broken(mentity) then return false
                if not accept_mentity_visibility(mentity) then return false
                if not accept_mentity_fictive(mentity) then return false
+               if not accept_mentity_generated(mentity) then return false
                if not accept_mentity_test(mentity) then return false
                if not accept_mentity_redef(mentity) then return false
                if not accept_mentity_extern(mentity) then return false
@@ -80,6 +99,28 @@ class ModelFilter
                return not mentity.is_fictive
        end
 
+       # Accept generated entities?
+       #
+       # Default is `true`.
+       var accept_generated = true is optional, writable
+
+       # Accept only non-generated entities
+       #
+       # See `MEntity::is_generated`.
+       fun accept_mentity_generated(mentity: MEntity): Bool do
+               if accept_generated then return true
+               if mentity isa MClass then mentity = mentity.intro
+               if mentity isa MProperty then mentity = mentity.intro
+               if mentity isa MModule then
+                       return not mentity.has_annotation("generated")
+               else if mentity isa MClassDef then
+                       return not mentity.has_annotation("generated")
+               else if mentity isa MPropDef then
+                       return not mentity.has_annotation("generated")
+               end
+               return true
+       end
+
        # Accept nitunit test suites?
        #
        # Default is `true`.
@@ -159,7 +200,7 @@ class ModelFilter
        # Accept examples?
        #
        # Default is `true`.
-       var accept_example = true is optional
+       var accept_example = true is optional, writable
 
        # Accept only entities that are not example related
        fun accept_mentity_example(mentity: MEntity): Bool do
@@ -168,7 +209,7 @@ class ModelFilter
        end
 
        # If set, accept only entities local to `accept_inherited`
-       var accept_inherited: nullable MEntity = null is optional
+       var accept_inherited: nullable MEntity = null is optional, writable
 
        # Accept only entities local to `accept_inherited`
        #
@@ -207,4 +248,15 @@ class ModelFilter
                if string == null then return true
                return mentity.full_name.has(string)
        end
+
+       # Accept broken classes and properties?
+       #
+       # Default is `false`.
+       var accept_broken = false is optional, writable
+
+       # Accept only non broken entities
+       fun accept_mentity_broken(mentity: MEntity): Bool do
+               if accept_broken then return true
+               return not mentity.is_broken
+       end
 end
index f8cfb24..f0c12fa 100644 (file)
@@ -29,8 +29,7 @@
 #
 # ~~~nitish
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      index.index(mentity)
 # end
 # ~~~
@@ -55,8 +54,7 @@
 #
 # ~~~nitish
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      # We don't really care about definitions
 #      if mentity isa MClassDef or mentity isa MPropDef then continue
 #      index.index(mentity)
 # ~~~
 module model_index
 
-import model::model_views
+import model::model_collect
+
 import trees::trie
+import trees::bktree
 
-redef class ModelView
+redef class Model
 
        # Keep a direct link to mentities by full name to speed up `mentity_from_uri`
        var mentities_by_full_name: HashMap[String, MEntity] is lazy do
                var mentities_by_full_name = new HashMap[String, MEntity]
-               for mentity in mentities do
+               for mentity in collect_mentities do
                        mentities_by_full_name[mentity.full_name] = mentity
                end
                return mentities_by_full_name
        end
 
        # ModelIndex used to perform searches
-       var index: ModelIndex is lazy do
+       var index: ModelIndex is lazy, writable do
                var index = new ModelIndex
-               for mentity in mentities do
+               for mentity in collect_mentities do
                        if mentity isa MClassDef or mentity isa MPropDef then continue
                        index.index mentity
                end
                return index
        end
 
-       redef fun mentities_by_name(name) do
-               if index.name_prefixes.has_key(name) then
-                       return index.name_prefixes[name]
+       redef fun mentities_by_name(name, filter) do
+               var res = new Array[MEntity]
+               if not index.names.has_key(name) then return res
+               for mentity in index.names[name] do
+                       if filter == null or filter.accept_mentity(mentity) then res.add mentity
                end
-               return new Array[MEntity]
+               return res
        end
 
-       redef fun mentity_by_full_name(full_name) do
+       redef fun mentity_by_full_name(full_name, filter) do
                if mentities_by_full_name.has_key(full_name) then
-                       return mentities_by_full_name[full_name]
+                       var mentity = mentities_by_full_name[full_name]
+                       if filter == null or filter.accept_mentity(mentity) then return mentity
                end
                return null
        end
@@ -175,7 +178,7 @@ redef class ModelView
 
        # Search mentities based on a `query` string
        #
-       # Lookup the view index for anything matching `query` and return `limit` results.
+       # Lookup the index for anything matching `query` and return `limit` results.
        #
        # The algorithm used is the following:
        # 1- lookup by name prefix
@@ -183,9 +186,9 @@ redef class ModelView
        # 3- loopup by levenshtein distance
        #
        # At each step if the `limit` is reached, the algorithm stops and returns the results.
-       fun find(query: String, limit: nullable Int): Array[MEntity] do
+       fun find(query: String, limit: nullable Int, filter: nullable ModelFilter): Array[MEntity] do
                # Find, lookup by name prefix
-               var matches = index.find_by_name_prefix(query).uniq.
+               var matches = index.find_by_name_prefix(query, filter).uniq.
                        sort(lname_sorter, name_sorter, kind_sorter)
                if limit != null and matches.length >= limit then
                        return matches.limit(limit).rerank.sort(vis_sorter, score_sorter).mentities
@@ -195,7 +198,7 @@ redef class ModelView
                # If limit not reached, lookup by full_name prefix
                var malus = matches.length
                var full_matches = new IndexMatches
-               for match in index.find_by_full_name_prefix(query).
+               for match in index.find_by_full_name_prefix(query, filter).
                        sort(kind_sorter, lfname_sorter, fname_sorter) do
                        match.score += malus
                        full_matches.add match
@@ -210,7 +213,7 @@ redef class ModelView
                # If limit not reached, lookup by similarity
                malus = matches.length
                var sim_matches = new IndexMatches
-               for match in index.find_by_similarity(query).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
+               for match in index.find_by_similarity(query, filter).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
                        match.score += malus
                        sim_matches.add match
                end
@@ -228,8 +231,7 @@ end
 # ~~~nitish
 # # Build index
 # var index = new ModelIndex
-# var view = new ModelView(model, mainmodule)
-# for mentity in view.mentities do
+# for mentity in model.collect_mentities do
 #      if mentity isa MClassDef or mentity isa MPropDef then continue
 #      index.index(mentity)
 # end
@@ -245,6 +247,9 @@ class ModelIndex
        # Faster than traversing the tries.
        var mentities = new Array[MEntity]
 
+       # Map of all mentities indexed by their `name`
+       var names = new HashMap[String, Array[MEntity]]
+
        # Prefix tree for mentities `name`
        #
        # Because multiple mentities can share the same `name`, we use a Trie of
@@ -254,30 +259,58 @@ class ModelIndex
        # TODO add an option.
        var name_prefixes = new Trie[Array[MEntity]]
 
+       # Distance tree for mentities `name`
+       var name_distances = new BKTree
+
+       # Map of all mentities indexed by their `full_name`
+       var full_names = new HashMap[String, MEntity]
+
        # Prefix tree for mentities `full_name`
        #
        # Even if two mentities cannot share the same `full_name`, we use a Trie of
        # arrays of mentities to be consistent with `name_prefixes`.
        var full_name_prefixes = new Trie[Array[MEntity]]
 
+       # Distance tree for mentities `full_name`
+       var full_name_distances = new BKTree
+
        # Index `mentity` by it's `MEntity::name`
        #
        # See `name_prefixes`.
        private fun index_by_name(mentity: MEntity) do
                var name = mentity.name
+
+               # Index name
+               if not names.has_key(name) then
+                       names[name] = new Array[MEntity]
+               end
+               names[name].add mentity
+
+               # Index prefix
                if not name_prefixes.has_key(name) then
                        name_prefixes[name] = new Array[MEntity]
                end
                name_prefixes[name].add mentity
+
+               # Index distance
+               name_distances.add(name)
        end
 
        # Index `mentity` by its `MEntity::full_name`
        private fun index_by_full_name(mentity: MEntity) do
                var name = mentity.full_name
+
+               # Index full name
+               full_names[name] = mentity
+
+               # Index prefix
                if not full_name_prefixes.has_key(name) then
                        full_name_prefixes[name] = new Array[MEntity]
                end
                full_name_prefixes[name].add mentity
+
+               # Index distance
+               full_name_distances.add(name)
        end
 
        # Index `mentity` so it can be retrieved by a find query
@@ -297,11 +330,12 @@ class ModelIndex
        # Results from the Trie are returned in a breadth first manner so we get the
        # matches ordered by prefix.
        # We preserve that order by giving an incremental score to the `array` items.
-       private fun score_results_incremental(array: Array[Array[MEntity]]): IndexMatches do
+       private fun score_results_incremental(array: Array[Array[MEntity]], filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
                var score = 1
                for mentities in array do
                        for mentity in mentities do
+                               if filter != null and not filter.accept_mentity(mentity) then continue
                                results.add new IndexMatch(mentity, score)
                        end
                        score += 1
@@ -310,24 +344,30 @@ class ModelIndex
        end
 
        # Find all mentities where `MEntity::name` matches the `prefix`
-       fun find_by_name_prefix(prefix: String): IndexMatches do
-               return score_results_incremental(name_prefixes.find_by_prefix(prefix))
+       fun find_by_name_prefix(prefix: String, filter: nullable ModelFilter): IndexMatches do
+               return score_results_incremental(name_prefixes.find_by_prefix(prefix), filter)
        end
 
        # Find all mentities where `MEntity::full_name` matches the `prefix`
-       fun find_by_full_name_prefix(prefix: String): IndexMatches do
-               return score_results_incremental(full_name_prefixes.find_by_prefix(prefix))
+       fun find_by_full_name_prefix(prefix: String, filter: nullable ModelFilter): IndexMatches do
+               return score_results_incremental(full_name_prefixes.find_by_prefix(prefix), filter)
        end
 
        # Rank all mentities by the distance between `MEntity::name` and `name`
        #
        # Use the Levenshtein algorithm on all the indexed mentities `name`.
        # Warning: may not scale to large indexes.
-       fun find_by_name_similarity(name: String): IndexMatches do
+       fun find_by_name_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
-               for mentity in mentities do
-                       if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
+               for match in name_distances.search(name) do
+                       var dist = match.distance
+                       var mname = match.key
+                       if not names.has_key(mname) then continue
+                       for mentity in names[mname] do
+                               if mentity isa MClassDef or mentity isa MPropDef then continue
+                               if filter != null and not filter.accept_mentity(mentity) then continue
+                               results.add new IndexMatch(mentity, dist)
+                       end
                end
                return results
        end
@@ -336,43 +376,39 @@ class ModelIndex
        #
        # Use the Levenshtein algorithm on all the indexed mentities `full_name`.
        # Warning: may not scale to large indexes.
-       fun find_by_full_name_similarity(name: String): IndexMatches do
+       fun find_by_full_name_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
-               for mentity in mentities do
+               for match in full_name_distances.search(name) do
+                       var dist = match.distance
+                       var mname = match.key
+                       if not full_names.has_key(mname) then continue
+                       var mentity = full_names[mname]
                        if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
+                       if filter != null and not filter.accept_mentity(mentity) then continue
+                       results.add new IndexMatch(mentity, dist)
                end
                return results
        end
 
        # Rank all mentities by the distance between `name` and both the mentity name and full name
-       fun find_by_similarity(name: String): IndexMatches do
+       fun find_by_similarity(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = new IndexMatches
-               for mentity in mentities do
-                       if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
-               end
+               results.add_all find_by_full_name_similarity(name, filter)
+               results.add_all find_by_name_similarity(name, filter)
                return results
        end
 
        # Find mentities by name trying first by prefix then by similarity
-       fun find_by_name(name: String): IndexMatches do
-               var results = find_by_name_prefix(name)
-               for mentity in mentities do
-                       if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
-               end
+       fun find_by_name(name: String, filter: nullable ModelFilter): IndexMatches do
+               var results = find_by_name_prefix(name, filter)
+               results.add_all find_by_name_similarity(name, filter)
                return results
        end
 
        # Find mentities by full name trying firt by prefix then by similarity
-       fun find_by_full_name(name: String): IndexMatches do
+       fun find_by_full_name(name: String, filter: nullable ModelFilter): IndexMatches do
                var results = find_by_full_name_prefix(name)
-               for mentity in mentities do
-                       if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
-               end
+               results.add_all find_by_full_name_similarity(name, filter)
                return results
        end
 
@@ -382,18 +418,10 @@ class ModelIndex
        # 2. add full name prefix matches
        # 3. try similarity by name
        # 4. try similarity by full_name
-       fun find(name: String): IndexMatches do
-               var results = find_by_name_prefix(name)
-
-               for result in find_by_full_name_prefix(name) do
-                       results.add result
-               end
-
-               for mentity in mentities do
-                       if mentity isa MClassDef or mentity isa MPropDef then continue
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.name))
-                       results.add new IndexMatch(mentity, name.levenshtein_distance(mentity.full_name))
-               end
+       fun find(name: String, filter: nullable ModelFilter): IndexMatches do
+               var results = find_by_name_prefix(name, filter)
+               results.add_all find_by_full_name_prefix(name, filter)
+               results.add_all find_by_similarity(name, filter)
                return results
        end
 end
diff --git a/src/model/model_views.nit b/src/model/model_views.nit
deleted file mode 100644 (file)
index cbf3fe2..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-# 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.
-
-module model_views
-
-import model_visitor
-
-# Provide a configurable view to a model.
-#
-# This can be useful when you need to filter some mentities from a model
-# like private or fictive.
-#
-# TODO doc usage
-class ModelView
-       super ModelVisitor
-
-       autoinit(model, mainmodule, filter)
-
-       # The model to view through `self`.
-       var model: Model
-
-       # MModule used to flatten mclass hierarchy
-       var mainmodule: MModule
-
-       # MPackages visible through `self`.
-       var mpackages: Set[MPackage] is lazy do
-               var mpackages = new HashSet[MPackage]
-               for mpackage in model.mpackages do
-                       if not accept_mentity(mpackage) then continue
-                       mpackages.add mpackage
-               end
-               return mpackages
-       end
-
-       # MGroups visible through `self`.
-       var mgroups: Set[MGroup] is lazy do
-               var mgroups = new HashSet[MGroup]
-               for mpackage in mpackages do
-                       for mgroup in mpackage.mgroups do
-                               if not accept_mentity(mgroup) then continue
-                               mgroups.add mgroup
-                       end
-               end
-               return mgroups
-       end
-
-       # MModules visible through `self`.
-       var mmodules: Set[MModule] is lazy do
-               var mmodules = new HashSet[MModule]
-               for mmodule in model.mmodules do
-                       if not accept_mentity(mmodule) then continue
-                       mmodules.add mmodule
-               end
-               return mmodules
-       end
-
-       # MClasses visible through `self`.
-       var mclasses: Set[MClass] is lazy do
-               var mclasses = new HashSet[MClass]
-               for mclass in model.mclasses do
-                       if not accept_mentity(mclass) then continue
-                       mclasses.add mclass
-               end
-               return mclasses
-       end
-
-       # MClassDefs visible through `self`.
-       var mclassdefs: Set[MClassDef] is lazy do
-               var mclassdefs = new HashSet[MClassDef]
-               for mclass in mclasses do
-                       for mclassdef in mclass.mclassdefs do
-                               if not accept_mentity(mclassdef) then continue
-                               mclassdefs.add mclassdef
-                       end
-               end
-               return mclassdefs
-       end
-
-       # MProperties visible through `self`.
-       var mproperties: Set[MProperty] is lazy do
-               var mproperties = new HashSet[MProperty]
-               for mproperty in model.mproperties do
-                       if not accept_mentity(mproperty) then continue
-                       mproperties.add mproperty
-               end
-               return mproperties
-       end
-
-       # MPropdefs visible through `self`.
-       var mpropdefs: Set[MPropDef] is lazy do
-               var mpropdefs = new HashSet[MPropDef]
-               for mproperty in mproperties do
-                       for mpropdef in mproperty.mpropdefs do
-                               if not accept_mentity(mpropdef) then continue
-                               mpropdefs.add mpropdef
-                       end
-               end
-               return mpropdefs
-       end
-
-       # Lists all MEntities visible through `self`.
-       var mentities: Set[MEntity] is lazy do
-               var res = new HashSet[MEntity]
-               res.add_all mpackages
-               res.add_all mgroups
-               res.add_all mmodules
-               res.add_all mclasses
-               res.add_all mclassdefs
-               res.add_all mproperties
-               res.add_all mpropdefs
-               return res
-       end
-
-       # Searches the MEntity that matches `full_name`.
-       fun mentity_by_full_name(full_name: String): nullable MEntity do
-               for mentity in mentities do
-                       if mentity.full_name == full_name then return mentity
-               end
-               return null
-       end
-
-       # Searches the MEntities that matches `full_name`.
-       fun mentities_by_name(name: String): Array[MEntity] do
-               var res = new Array[MEntity]
-               for mentity in mentities do
-                       if mentity.name == name then res.add mentity
-               end
-               return res
-       end
-
-       # Build an concerns tree with from `self`
-       fun to_tree: MEntityTree do
-               var v = new ModelTreeVisitor
-               v.filter = self.filter
-               for mpackage in mpackages do
-                       v.enter_visit(mpackage)
-               end
-               return v.tree
-       end
-
-       # Build the POSet of `mmodules` importation.
-       fun mmodules_poset(mmodules: Set[MModule]): POSet[MModule] do
-               return model.mmodule_importation_hierarchy.sub(mmodules)
-       end
-
-       # Build the POSet of `mclasses` hierarchy.
-       fun mclasses_poset(mainmodule: MModule, mclasses: Set[MClass]): POSet[MClass] do
-               return mainmodule.flatten_mclass_hierarchy.sub(mclasses)
-       end
-end
-
-class LookupNamespaceVisitor
-       super ModelVisitor
-
-       var namespace: String
-
-       private var parts: Array[String] is lazy do return namespace.split_with("::")
-
-       var results = new Array[MEntity]
-
-       redef fun visit(mentity) do mentity.accept_namespace_visitor(self)
-end
-
-class ModelTreeVisitor
-       super ModelVisitor
-
-       var tree = new MEntityTree
-
-       redef fun visit(mentity) do mentity.accept_tree_visitor(self)
-end
-
-redef class MEntity
-       private fun accept_namespace_visitor(v: LookupNamespaceVisitor) do
-               if v.parts.is_empty then return
-               if name != v.parts.first then return
-               v.parts.shift
-               if v.parts.is_empty then
-                       v.results.add self
-                       return
-               end
-               visit_all(v)
-       end
-
-       private fun accept_tree_visitor(v: ModelTreeVisitor) do end
-end
-
-redef class MPackage
-       redef fun accept_tree_visitor(v) do
-               v.tree.add(null, self)
-               visit_all(v)
-       end
-end
-
-redef class MGroup
-       redef fun accept_tree_visitor(v) do
-               var parent = self.parent
-               if parent != null then
-                       v.tree.add(parent, self)
-               else
-                       v.tree.add(mpackage, self)
-               end
-               visit_all(v)
-       end
-end
-
-redef class MModule
-       redef fun accept_tree_visitor(v) do
-               v.tree.add(mgroup, self)
-               visit_all(v)
-       end
-end
-
-redef class MClass
-       # We don't want to collect classes from full namespace.
-       redef fun accept_namespace_visitor(v) do end
-end
-
-redef class MClassDef
-       redef fun accept_tree_visitor(v) do
-               v.tree.add(mmodule, self)
-               visit_all(v)
-       end
-end
-
-redef class MProperty
-       # We don't want to collect properties from full namespace.
-       redef fun accept_namespace_visitor(v) do end
-end
-
-redef class MPropDef
-       redef fun accept_tree_visitor(v) do
-               v.tree.add(mclassdef, self)
-               visit_all(v)
-       end
-end
index 3157233..1cdde49 100644 (file)
@@ -92,6 +92,21 @@ class MPackage
                if ini_path == null then return false
                return ini_path.file_exists
        end
+
+       # The path to `self` README.md
+       fun readme_path: nullable String do
+               var path = package_path
+               if path == null then return null
+               if not is_expanded then return null
+               return path / "README.md"
+       end
+
+       # Does `self` have a README.md file?
+       fun has_readme: Bool do
+               var readme_path = self.readme_path
+               if readme_path == null then return false
+               return readme_path.file_exists
+       end
 end
 
 # A group of modules in a package
index 2ae2b59..c8a7f3b 100644 (file)
@@ -1463,9 +1463,7 @@ redef class AAttrPropdef
                        if cla != null then mtype = cla.mclass_type
                else if nexpr isa ACharExpr then
                        var cla: nullable MClass
-                       if nexpr.is_ascii then
-                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
-                       else if nexpr.is_code_point then
+                       if nexpr.is_code_point then
                                cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
                        else
                                cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
index 244be79..2a0a4a5 100644 (file)
 module nitcatalog
 
 import loader # Scan&load packages, groups and modules
-import doc::doc_down # Display mdoc
 import catalog
 
+import doc::templates::html_model
+
 # A HTML page in a catalog
 #
 # This is just a template with the header pre-filled and the footer injected at rendering.
@@ -531,6 +532,24 @@ redef class Catalog
        var piwik_site_id: Int = 1
 end
 
+redef class Person
+       redef fun to_html do
+               var res = ""
+               var e = name.html_escape
+               var page = self.page
+               if page != null then
+                       res += "<a href=\"{page.html_escape}\">"
+               end
+               var gravatar = self.gravatar
+               if gravatar != null then
+                       res += "<img src=\"https://secure.gravatar.com/avatar/{gravatar}?size=20&amp;default=retro\">&nbsp;"
+               end
+               res += e
+               if page != null then res += "</a>"
+               return res
+       end
+end
+
 var model = new Model
 var tc = new ToolContext
 
index 159c771..65227b3 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Documentation generator for the nit language.
+# Generator of static API documentation for the Nit language
 #
-# Generate API documentation in HTML format from nit source code.
+# Generate API documentation in HTML format from Nit source code.
 module nitdoc
 
-import modelbuilder
-import doc
+import doc::static
 
 redef class ToolContext
-       # Nitdoc generation phase.
+
+       # Nitdoc generation phase
        var docphase: Phase = new Nitdoc(self, null)
 
-       # Do not generate documentation for attributes.
+       # Directory where the Nitdoc is rendered
+       var opt_dir = new OptionString("Output directory", "-d", "--dir")
+
+       # Do not generate documentation for attributes
        var opt_no_attributes = new OptionBool("Ignore the attributes", "--no-attributes")
 
-       # Do not generate documentation for private properties.
+       # Do not generate documentation for private properties
        var opt_private = new OptionBool("Also generate private API", "--private")
 
+       # Use a shareurl instead of copy shared files
+       #
+       # This is usefull if you don't want to store the Nitdoc templates with your
+       # documentation.
+       var opt_shareurl = new OptionString("Use shareurl instead of copy shared files", "--shareurl")
+
+       # Use a custom title for the homepage
+       var opt_custom_title = new OptionString("Custom title for homepage", "--custom-title")
+
+       # Display a custom brand or logo in the documentation top menu
+       var opt_custom_brand = new OptionString("Custom link to external site", "--custom-brand")
+
+       # Display a custom introduction text before the packages overview
+       var opt_custom_intro = new OptionString("Custom intro text for homepage", "--custom-overview-text")
+
+       # Display a custom footer on each documentation page
+       #
+       # Generally used to display the documentation or product version.
+       var opt_custom_footer = new OptionString("Custom footer text", "--custom-footer-text")
+
+       # Piwik tracker URL
+       #
+       # If you want to monitor your visitors.
+       var opt_piwik_tracker = new OptionString("Piwik tracker URL (ex: `nitlanguage.org/piwik/`)", "--piwik-tracker")
+
+       # Piwik tracker site id
+       var opt_piwik_site_id = new OptionString("Piwik site ID", "--piwik-site-id")
+
+       # Do not generate dot/graphviz diagrams
+       var opt_nodot = new OptionBool("Do not generate graphs with graphviz", "--no-dot")
+
+       # Do not include highlighted code
+       var opt_nocode = new OptionBool("Do not generate code with nitlight", "--no-code")
+
+       # File pattern used to link documentation to source code.
+       var opt_source = new OptionString("Format to link source code (%f for filename, " +
+               "%l for first line, %L for last line) only works with option --no-code", "--source")
+
+       # Disable HTML rendering
+       var opt_norender = new OptionBool("DO not render any HTML", "--no-render")
+
+       # Test mode
+       #
+       # Display test data and remove the progress bar
+       var opt_test = new OptionBool("Output test data", "--test")
+
        redef init do
                super
-               option_context.add_option(opt_no_attributes, opt_private)
+               option_context.add_option(
+                       opt_dir, opt_no_attributes, opt_private,
+                       opt_share_dir, opt_shareurl, opt_custom_title,
+                       opt_custom_footer, opt_custom_intro, opt_custom_brand,
+                       opt_piwik_tracker, opt_piwik_site_id,
+                       opt_nodot, opt_nocode, opt_source, opt_norender, opt_test)
+       end
+end
+
+redef class DocModel
+
+       # Generate a documentation page
+       fun gen_page(page: DocPage, output_dir: String) do
+               page.apply_structure(self)
+               page.render(self).write_to_file("{output_dir}/{page.html_url}")
        end
 end
 
-# Nitdoc phase explores the model and generate pages for each mentities found
+# Nitdoc phase explores the model and generate pages for each mentity found
 private class Nitdoc
        super Phase
+
        redef fun process_mainmodule(mainmodule, mmodules)
        do
+               var modelbuilder = toolcontext.modelbuilder
+               var model = modelbuilder.model
+
                var min_visibility = private_visibility
                if not toolcontext.opt_private.value then min_visibility = protected_visibility
                var accept_attribute = true
                if toolcontext.opt_no_attributes.value then accept_attribute = false
 
-               var filters = new ModelFilter(
+               var catalog = new Catalog(toolcontext.modelbuilder)
+               catalog.build_catalog(mainmodule.model.mpackages)
+
+               var filter = new ModelFilter(
                        min_visibility,
                        accept_attribute = accept_attribute,
-                       accept_fictive = false)
-               var doc = new DocModel(mainmodule.model, mainmodule, filters)
-
-               var phases = [
-                       new IndexingPhase(toolcontext, doc),
-                       new MakePagePhase(toolcontext, doc),
-                       new POSetPhase(toolcontext, doc),
-                       new ConcernsPhase(toolcontext, doc),
-                       new StructurePhase(toolcontext, doc),
-                       new InheritanceListsPhase(toolcontext, doc),
-                       new IntroRedefListPhase(toolcontext, doc),
-                       new LinListPhase(toolcontext, doc),
-                       new GraphPhase(toolcontext, doc),
-                       new ReadmePhase(toolcontext, doc),
-                       new RenderHTMLPhase(toolcontext, doc),
-                       new DocTestPhase(toolcontext, doc): DocPhase]
-
-               for phase in phases do
-                       toolcontext.info("# {phase.class_name}", 1)
-                       phase.apply
+                       accept_fictive = true,
+                       accept_generated = true,
+                       accept_test = false,
+                       accept_redef = true,
+                       accept_extern = true,
+                       accept_empty_doc = true,
+                       accept_example = true,
+                       accept_broken = false)
+
+               var doc = new DocModel(model, mainmodule, modelbuilder, catalog, filter)
+
+               model.nitdoc_md_processor = doc.md_processor
+               doc.no_dot = toolcontext.opt_nodot.value
+               doc.no_code = toolcontext.opt_nocode.value
+               doc.code_url = toolcontext.opt_source.value
+               doc.share_url = toolcontext.opt_shareurl.value
+               doc.custom_brand = toolcontext.opt_custom_brand.value
+               doc.custom_title = toolcontext.opt_custom_title.value
+               doc.custom_footer = toolcontext.opt_custom_footer.value
+               doc.custom_intro = toolcontext.opt_custom_intro.value
+               doc.tracker_url = toolcontext.opt_piwik_tracker.value
+               doc.piwik_site_id = toolcontext.opt_piwik_site_id.value
+
+               # Prepare output dir
+               var test_mode = toolcontext.opt_test.value
+               var no_render = toolcontext.opt_norender.value
+               var output_dir = toolcontext.opt_dir.value or else "doc"
+
+               if not no_render then
+                       output_dir.mkdir
+
+                       # Copy assets
+                       var share_dir = toolcontext.opt_share_dir.value or else "{toolcontext.share_dir}/nitdoc"
+                       sys.system("cp -r -- {share_dir.escape_to_sh}/* {output_dir.escape_to_sh}/")
+               end
+
+               # Collect model to document
+               var mpackages = model.collect_mpackages(filter)
+               var mgroups = model.collect_mgroups(filter)
+               var nmodules = model.collect_mmodules(filter)
+               var mclasses = model.collect_mclasses(filter)
+               var mprops = model.collect_mproperties(filter)
+
+               var mentities = new Array[MEntity]
+               mentities.add_all mpackages
+               mentities.add_all mgroups
+               mentities.add_all nmodules
+               mentities.add_all mclasses
+               mentities.add_all mprops
+
+               var persons = doc.catalog.persons
+               var tags = doc.catalog.tag2proj.keys
+
+               # Prepare progress bar
+               var count = 0
+               var pages = 1 # count homepage
+               pages += mentities.length
+               pages += persons.length
+               pages += tags.length
+
+               print "Generating documentation pages..."
+               var progress = new TermProgress(pages, 0)
+               if not test_mode then progress.display
+
+               # Make pages
+               count += 1
+               if not test_mode then progress.update(count, "homepage")
+               if not no_render then doc.gen_page(new PageHome("Overview"), output_dir)
+
+               for mentity in mentities do
+                       count += 1
+                       if not test_mode then progress.update(count, "page {count}/{pages}")
+                       if not no_render then doc.gen_page(new PageMEntity(mentity), output_dir)
+               end
+               for name, person in persons do
+                       count += 1
+                       if not test_mode then progress.update(count, "page {count}/{pages}")
+                       if not no_render then doc.gen_page(new PagePerson(person), output_dir)
+               end
+               for tag in tags do
+                       count += 1
+                       if not test_mode then progress.update(count, "page {count}/{pages}")
+                       if not no_render then doc.gen_page(new PageTag(tag), output_dir)
+               end
+
+               if not test_mode then  print "" # finalise progress
+               if not no_render then
+                       doc.create_index_file("{output_dir}/quicksearch-list.js")
+                       print "Documentation produced in `{output_dir}`"
+               end
+
+               if test_mode then
+                       print "Generated {count}/{pages} pages"
+                       print " PageHome: 1"
+                       print " PageMPackage: {mpackages.length}"
+                       print " PageMGroup: {mgroups.length}"
+                       print " PageMModule: {nmodules.length}"
+                       print " PageMClass: {mclasses.length}"
+                       print " PageMProperty: {mprops.length}"
+                       print " PagePerson: {persons.length}"
+                       print " PageTag: {tags.length}"
+               end
+       end
+end
+
+redef class Catalog
+
+       # Build the catalog from `mpackages`
+       fun build_catalog(mpackages: Array[MPackage]) do
+               # Compute the poset
+               for p in mpackages do
+                       var g = p.root
+                       assert g != null
+                       modelbuilder.scan_group(g)
+
+                       deps.add_node(p)
+                       for gg in p.mgroups do for m in gg.mmodules do
+                               for im in m.in_importation.direct_greaters do
+                                       var ip = im.mpackage
+                                       if ip == null or ip == p then continue
+                                       deps.add_edge(p, ip)
+                               end
+                       end
+               end
+               # Build the catalog
+               for mpackage in mpackages do
+                       package_page(mpackage)
+                       git_info(mpackage)
+                       mpackage_stats(mpackage)
                end
        end
 end
@@ -91,5 +270,6 @@ var mmodules = mbuilder.parse_full(arguments)
 
 # process
 if mmodules.is_empty then return
+print "Parsing code..."
 mbuilder.run_phases
 toolcontext.run_global_phases(mmodules)
index 4321214..62fc09f 100644 (file)
@@ -196,7 +196,9 @@ end
 if opt_source.value then
        alpha_comparator.sort(mmodules)
        for mp in mmodules do
-               if opt_paths.value then
+               if opt_make.value then
+                       print mp.filepath.escape_to_mk
+               else if opt_paths.value then
                        print mp.filepath.as(not null)
                else
                        print "{mp.mgroup.full_name}{ot.display(mp)}"
index bb6fb42..a81ded9 100644 (file)
@@ -19,6 +19,10 @@ import frontend
 import doc::commands::commands_main
 
 redef class ToolContext
+
+       # nitpackage phase
+       var nitpackage_phase: Phase = new NitPackagePhase(self, null)
+
        # --expand
        var opt_expand = new OptionBool("Move singleton packages to their own directory", "--expand")
 
@@ -37,21 +41,22 @@ redef class ToolContext
        # --gen-makefile
        var opt_gen_makefile = new OptionBool("Generate Makefile files", "--gen-makefile")
 
-       # nitpackage phase
-       var nitpackage_phase: Phase = new NitPackagePhase(self, null)
-
        # --check-man
        var opt_check_man = new OptionBool("Check manpages files", "--check-man")
 
        # --gen-man
        var opt_gen_man = new OptionBool("Generate manpages files", "--gen-man")
 
+       # --check-readme
+       var opt_check_readme = new OptionBool("Check README.md files", "--check-readme")
+
        redef init do
                super
                option_context.add_option(opt_expand, opt_force)
                option_context.add_option(opt_check_ini, opt_gen_ini)
                option_context.add_option(opt_check_makefile, opt_gen_makefile)
                option_context.add_option(opt_check_man, opt_gen_man)
+               option_context.add_option(opt_check_readme)
        end
 end
 
@@ -87,6 +92,12 @@ private class NitPackagePhase
                                continue
                        end
 
+                       # Check README.md
+                       if toolcontext.opt_check_readme.value then
+                               mpackage.check_readme(toolcontext)
+                               continue
+                       end
+
                        # Expand packages
                        if toolcontext.opt_expand.value and not mpackage.is_expanded then
                                var path = mpackage.expand
@@ -317,9 +328,8 @@ redef class MPackage
        private fun check_makefile(toolcontext: ToolContext, mainmodule: MModule) do
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(accept_example = false, accept_test = false)
-               var view = new ModelView(model, mainmodule, filter)
 
-               var cmd_bin = new CmdMains(view, mentity = self)
+               var cmd_bin = new CmdMains(model, filter, mentity = self)
                var res_bin = cmd_bin.init_command
                if not res_bin isa CmdSuccess then return
 
@@ -335,13 +345,12 @@ redef class MPackage
 
        private fun gen_makefile(model: Model, mainmodule: MModule): nullable String do
                var filter = new ModelFilter(accept_example = false, accept_test = false)
-               var view = new ModelView(model, mainmodule, filter)
 
                var pkg_path = package_path.as(not null)
                var makefile_path = makefile_path.as(not null)
 
                var bins = new Array[String]
-               var cmd_bin = new CmdMains(view, mentity = self)
+               var cmd_bin = new CmdMains(model, filter, mentity = self)
                var res_bin = cmd_bin.init_command
                if res_bin isa CmdSuccess then
                        for mmodule in cmd_bin.results.as(not null) do
@@ -389,9 +398,7 @@ redef class MPackage
        private fun check_man(toolcontext: ToolContext, mainmodule: MModule) do
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(accept_example = false, accept_test = false)
-               var view = new ModelView(model, mainmodule, filter)
-
-               var cmd = new CmdMains(view, mentity = self)
+               var cmd = new CmdMains(model, filter, mentity = self)
                var res = cmd.init_command
                if not res isa CmdSuccess then return
 
@@ -404,9 +411,7 @@ redef class MPackage
        private fun gen_man(toolcontext: ToolContext, mainmodule: MModule) do
                var model = toolcontext.modelbuilder.model
                var filter = new ModelFilter(accept_example = false, accept_test = false)
-               var view = new ModelView(model, mainmodule, filter)
-
-               var cmd = new CmdMains(view, mentity = self)
+               var cmd = new CmdMains(model, filter, mentity = self)
                var res = cmd.init_command
                if not res isa CmdSuccess then return
 
@@ -417,6 +422,15 @@ redef class MPackage
                        mmodule.gen_man(toolcontext)
                end
        end
+
+       # README
+
+       private fun check_readme(toolcontext: ToolContext) do
+               if not has_readme then
+                       toolcontext.error(location, "No `README.md` file for `{name}`")
+                       return
+               end
+       end
 end
 
 redef class MModule
index 0b9bf72..2723a8b 100644 (file)
@@ -46,8 +46,7 @@ private class UMLPhase
                        filters.min_visibility = protected_visibility
                end
 
-               var view = new ModelView(mainmodule.model, mainmodule, filters)
-               var d = new UMLModel(view, mainmodule)
+               var d = new UMLModel(toolcontext.modelbuilder.model, mainmodule, filters)
                if toolcontext.opt_gen.value == 0 then
                        print d.generate_class_uml.write_to_string
                else if toolcontext.opt_gen.value == 1 then
index 3617df4..9e9d54f 100644 (file)
@@ -17,7 +17,6 @@ module nitweb
 
 import frontend
 import doc::api
-import doc::doc_down
 
 redef class ToolContext
 
@@ -72,9 +71,9 @@ private class NitwebPhase
                        accept_attribute = not toolcontext.opt_no_attribute.value
                )
 
-               var view = new ModelView(model, mainmodule, filter)
+               var catalog = build_catalog(toolcontext.modelbuilder, filter)
 
-               var config = new NitwebConfig(model, mainmodule, toolcontext.modelbuilder, view)
+               var config = new NitwebConfig(model, mainmodule, toolcontext.modelbuilder, filter, catalog)
                var config_file = toolcontext.opt_config.value
                if config_file == null then config.default_config_file = "nitweb.ini"
                config.parse_options(args)
@@ -88,8 +87,8 @@ private class NitwebPhase
        redef fun process_mainmodule(mainmodule, mmodules)
        do
                var config = build_config(toolcontext, mainmodule)
+               config.model.index # pre load model index
                config.model.nitdoc_md_processor = config.md_processor
-               config.build_catalog
 
                var app = new App
 
@@ -104,6 +103,37 @@ private class NitwebPhase
 
                app.listen(config.app_host, config.app_port)
        end
+
+       # Build the catalog
+       #
+       # This method should be called at nitweb startup.
+       fun build_catalog(modelbuilder: ModelBuilder, filter: nullable ModelFilter): Catalog do
+               var catalog = new Catalog(modelbuilder)
+               var mpackages = modelbuilder.model.collect_mpackages(filter)
+               # Compute the poset
+               for p in mpackages do
+                       var g = p.root
+                       assert g != null
+                       modelbuilder.scan_group(g)
+
+                       catalog.deps.add_node(p)
+                       for gg in p.mgroups do for m in gg.mmodules do
+                               for im in m.in_importation.direct_greaters do
+                                       var ip = im.mpackage
+                                       if ip == null or ip == p then continue
+                                       catalog.deps.add_edge(p, ip)
+                               end
+                       end
+               end
+               # Build the catalog
+               for mpackage in mpackages do
+                       catalog.package_page(mpackage)
+                       catalog.git_info(mpackage)
+                       catalog.mpackage_stats(mpackage)
+               end
+               return catalog
+       end
+
 end
 
 # build toolcontext
index 8442ff7..311580a 100644 (file)
@@ -43,8 +43,11 @@ end
 # Using `prompt`, the command line can be turned on an interactive tool.
 class Nitx
 
-       # ModelView that contains the informations to display
-       var view: ModelView
+       # Model that contains the informations to display
+       var model: Model
+
+       # Mainmodule for class linearization
+       var mainmodule: MModule
 
        # ModelBuilder to access AST nodes
        var modelbuilder: ModelBuilder
@@ -66,7 +69,7 @@ class Nitx
                print "Welcome in the Nit Index!"
                print ""
                print "Loaded packages:\n"
-               var cmd = new CmdModelEntities(view, kind = "packages")
+               var cmd = new CmdModelEntities(model, kind = "packages")
                cmd.init_command
                for mpackage in cmd.results.as(not null) do
                        print " * {mpackage.full_name}"
@@ -101,7 +104,7 @@ class Nitx
        end
 
        # Parser used to process doc commands
-       var parser = new CommandParser(view, modelbuilder, catalog) is lazy
+       var parser = new CommandParser(model, mainmodule, modelbuilder, catalog) is lazy
 
        # Processes the query string and performs it.
        fun do_command(str: String) do
@@ -117,9 +120,9 @@ end
 
 redef class Catalog
        # Build the catalog for Nitx
-       private fun build_catalog(view: ModelView) do
+       private fun build_catalog(model: Model, filter: nullable ModelFilter) do
                # Compute the poset
-               for p in view.mpackages do
+               for p in model.collect_mpackages(filter) do
                        var g = p.root
                        assert g != null
                        modelbuilder.scan_group(g)
@@ -134,7 +137,7 @@ redef class Catalog
                        end
                end
                # Build the catalog
-               for mpackage in view.mpackages do
+               for mpackage in model.collect_mpackages(filter) do
                        package_page(mpackage)
                        git_info(mpackage)
                        mpackage_stats(mpackage)
@@ -165,15 +168,14 @@ toolcontext.run_global_phases(mmodules)
 var mainmodule = toolcontext.make_main_module(mmodules)
 
 # build views
-var view = new ModelView(model, mainmodule)
 var catalog = null
 if toolcontext.opt_catalog.value then
        catalog = new Catalog(mbuilder)
-       catalog.build_catalog(view)
+       catalog.build_catalog(model)
 end
 
 # start nitx
-var nitx = new Nitx(view, mbuilder, catalog, toolcontext.opt_no_color.value)
+var nitx = new Nitx(model, mainmodule, mbuilder, catalog, toolcontext.opt_no_color.value)
 var q = toolcontext.opt_command.value
 if q != null then # shortcut prompt
        print ""
index 3297d12..3463b07 100644 (file)
@@ -1577,9 +1577,7 @@ end
 redef class ACharExpr
        redef fun accept_typing(v) do
                var mclass: nullable MClass = null
-               if is_ascii then
-                       mclass = v.get_mclass(self, "Byte")
-               else if is_code_point then
+               if is_code_point then
                        mclass = v.get_mclass(self, "Int")
                else
                        mclass = v.get_mclass(self, "Char")
index 74e0b4c..d17b7db 100644 (file)
 import frontend
 import model_index
 import console
+import realtime
 
 redef class ToolContext
+       var opt_query = new OptionString("String to search", "-q", "--query")
        var opt_name_prefix = new OptionBool("", "--name-prefix")
        var opt_full_name_prefix = new OptionBool("", "--full-name-prefix")
        var opt_name_similarity = new OptionBool("", "--name-similarity")
@@ -25,6 +27,7 @@ redef class ToolContext
        var opt_full_name = new OptionBool("", "--full-name")
 
        redef init do
+               option_context.add_option(opt_query)
                option_context.add_option(opt_name_prefix, opt_full_name_prefix)
                option_context.add_option(opt_name_similarity, opt_full_name_similarity)
                option_context.add_option(opt_name, opt_full_name)
@@ -43,69 +46,89 @@ redef class MEntity
        end
 end
 
+fun search(index: ModelIndex, toolcontext: ToolContext, query: String): Float do
+       var clock = new Clock
+       print "# {query}\n"
+
+       var res
+       if toolcontext.opt_name_prefix.value then
+               res = index.find_by_name_prefix(query)
+       else if toolcontext.opt_full_name_prefix.value then
+               res = index.find_by_full_name_prefix(query)
+       else if toolcontext.opt_name_similarity.value then
+               res = index.find_by_name_similarity(query)
+       else if toolcontext.opt_full_name_similarity.value then
+               res = index.find_by_full_name_similarity(query)
+       else if toolcontext.opt_name.value then
+               res = index.find_by_name(query)
+       else if toolcontext.opt_full_name.value then
+               res = index.find_by_full_name(query)
+       else
+               res = index.find(query)
+       end
+
+       res = res.sort(new ScoreComparator, new MEntityComparator).
+                       uniq.
+                       limit(10).
+                       sort(new VisibilityComparator, new NameComparator)
+
+       for e in res do
+               if toolcontext.opt_no_color.value then
+                       print " * {e.score}: {e.mentity.name} ({e.mentity.full_name})"
+               else
+                       print " * {e.score}: {e.mentity.color} ({e.mentity.full_name})"
+               end
+       end
+       return clock.total
+end
+
 # build toolcontext
 var toolcontext = new ToolContext
 toolcontext.process_options(args)
 var args = toolcontext.option_context.rest
 
-if not args.length == 2 then
-       print "usage: test_model_index <nitfile> <search_query>"
+if args.is_empty then
+       print "usage: test_model_index nitfiles..."
        exit 1
+       return
 end
 
 # build model
 var model = new Model
 var mbuilder = new ModelBuilder(model, toolcontext)
-var mmodules = mbuilder.parse_full([args.first])
+var mmodules = mbuilder.parse_full(args)
 
 # process
 if mmodules.is_empty then return
 mbuilder.run_phases
 toolcontext.run_global_phases(mmodules)
-var mainmodule = toolcontext.make_main_module(mmodules)
 
 # Build index
 var filters = new ModelFilter(
        private_visibility,
        accept_fictive = false,
        accept_test = false)
-var view = new ModelView(model, mainmodule, filters)
 var index = new ModelIndex
-for mentity in view.mentities do
+for mentity in model.collect_mentities(filters) do
        if mentity isa MClassDef or mentity isa MPropDef then continue
        index.index(mentity)
 end
 
-var q = args[1]
-
-print "# {q}\n"
-
-var res
-if toolcontext.opt_name_prefix.value then
-       res = index.find_by_name_prefix(q)
-else if toolcontext.opt_full_name_prefix.value then
-       res = index.find_by_full_name_prefix(q)
-else if toolcontext.opt_name_similarity.value then
-       res = index.find_by_name_similarity(q)
-else if toolcontext.opt_full_name_similarity.value then
-       res = index.find_by_full_name_similarity(q)
-else if toolcontext.opt_name.value then
-       res = index.find_by_name(q)
-else if toolcontext.opt_full_name.value then
-       res = index.find_by_full_name(q)
-else
-       res = index.find(q)
-end
-
-res = res.sort(new ScoreComparator, new MEntityComparator).
-               uniq.
-               limit(10).
-               sort(new VisibilityComparator, new NameComparator)
-
-for e in res do
-       if toolcontext.opt_no_color.value then
-               print " * {e.score}: {e.mentity.name} ({e.mentity.full_name})"
-       else
-               print " * {e.score}: {e.mentity.color} ({e.mentity.full_name})"
+var query = toolcontext.opt_query.value
+if query == null then
+       print "# Interactive mode, type `:q` to quit\n\n"
+       printn "> "
+       var line = stdin.read_line
+       while line != ":q" do
+               print ""
+               var time = search(index, toolcontext, line.trim)
+               print ""
+               print "Query executed in {time} seconds."
+               print ""
+               printn "> "
+               line = stdin.read_line
        end
+       return
 end
+
+search(index, toolcontext, query)
index 0121162..46f5a4a 100644 (file)
@@ -17,13 +17,12 @@ module testing_doc
 
 private import parser_util
 import testing_base
-import markdown
+import markdown2
 import html
 import realtime
 
 # Extractor, Executor and Reporter for the tests in a module
 class NitUnitExecutor
-       super HTMLDecorator
 
        # Toolcontext used to parse Nit code blocks.
        var toolcontext: ToolContext
@@ -40,12 +39,11 @@ class NitUnitExecutor
        # The name of the suite
        var name: String
 
-       # Markdown processor used to parse markdown comments and extract code.
-       var mdproc = new MarkdownProcessor
+       # Markdown parse used to parse markdown comments and extract code
+       private var md_parser = new MdParser
 
-       init do
-               mdproc.decorator = new NitunitDecorator(self)
-       end
+       # Markdown visitor used to extract markdown code blocks
+       private var md_visitor = new NitunitMdVisitor(self) is lazy
 
        # The associated documentation object
        var mdoc: nullable MDoc = null
@@ -58,8 +56,10 @@ class NitUnitExecutor
        # Is used because a new code-block might just be added to it.
        var last_docunit: nullable DocUnit = null
 
+       # Unit class name in XML output
        var xml_classname: String is noautoinit
 
+       # Unit name in xml output
        var xml_name: String is noautoinit
 
        # The entry point for a new `ndoc` node
@@ -73,17 +73,17 @@ class NitUnitExecutor
                self.mdoc = mdoc
 
                # Populate `blocks` from the markdown decorator
-               mdproc.process(mdoc.content.join("\n"))
+               var md_node = md_parser.parse(mdoc.content.join("\n"))
+               md_visitor.enter_visit(md_node)
        end
 
        # All extracted docunits
        var docunits = new Array[DocUnit]
 
-       fun show_status
-       do
-               toolcontext.show_unit_status(name, docunits)
-       end
+       # Display current testing status
+       fun show_status do toolcontext.show_unit_status(name, docunits)
 
+       # Update display when a test case is done
        fun mark_done(du: DocUnit)
        do
                du.is_done = true
@@ -100,7 +100,8 @@ class NitUnitExecutor
                end
 
                # Try to group each nitunit into a single source file to fasten the compilation
-               var simple_du = new Array[DocUnit]
+               var simple_du = new Array[DocUnit] # du that are simple statements
+               var single_du = new Array[DocUnit] # du that are modules or include classes
                show_status
                for du in docunits do
                        # Skip existing errors
@@ -111,19 +112,27 @@ class NitUnitExecutor
                        var ast = toolcontext.parse_something(du.block)
                        if ast isa AExpr then
                                simple_du.add du
+                       else
+                               single_du.add du
                        end
                end
-               test_simple_docunits(simple_du)
+
+               # Try to mass compile all the simple du as a single nit module
+               compile_simple_docunits(simple_du)
+               # Try to mass compile all the single du in a single nitc invocation with many modules
+               compile_single_docunits(single_du)
+               # If the mass compilation fail, then each one will be compiled individually
 
                # Now test them in order
                for du in docunits do
                        if du.error != null then
                                # Nothing to execute. Conclude
-                       else if du.test_file != null then
+                       else if du.is_compiled then
                                # Already compiled. Execute it.
                                execute_simple_docunit(du)
                        else
-                               # Need to try to compile it, then execute it
+                               # A mass compilation failed
+                               # Need to try to recompile it, then execute it
                                test_single_docunit(du)
                        end
                        mark_done(du)
@@ -138,25 +147,29 @@ class NitUnitExecutor
                end
        end
 
-       # Executes multiples doc-units in a shared program.
+       # Compiles multiples doc-units in a shared program.
        # Used for docunits simple block of code (without modules, classes, functions etc.)
        #
-       # In case of compilation error, the method fallbacks to `test_single_docunit` to
+       # In case of success, the docunits are compiled and the caller can call `execute_simple_docunit`.
+       #
+       # In case of compilation error, the docunits are let uncompiled.
+       # The caller should fallbacks to `test_single_docunit` to
        # * locate exactly the compilation problem in the problematic docunit.
        # * permit the execution of the other docunits that may be correct.
-       fun test_simple_docunits(dus: Array[DocUnit])
+       fun compile_simple_docunits(dus: Array[DocUnit])
        do
                if dus.is_empty then return
 
                var file = "{prefix}-0.nit"
 
+               toolcontext.info("Compile {dus.length} simple(s) doc-unit(s) in {file}", 1)
+
                var dir = file.dirname
                if dir != "" then dir.mkdir
                var f
                f = create_unitfile(file)
                var i = 0
                for du in dus do
-
                        i += 1
                        f.write("fun run_{i} do\n")
                        f.write("# {du.full_name}\n")
@@ -175,7 +188,7 @@ class NitUnitExecutor
 
                if res != 0 then
                        # Compilation error.
-                       # They will be executed independently
+                       # They should be generated and compiled independently
                        return
                end
 
@@ -186,6 +199,7 @@ class NitUnitExecutor
                        i += 1
                        du.test_file = file
                        du.test_arg = i
+                       du.is_compiled = true
                end
        end
 
@@ -193,7 +207,7 @@ class NitUnitExecutor
        fun execute_simple_docunit(du: DocUnit)
        do
                var file = du.test_file.as(not null)
-               var i = du.test_arg.as(not null)
+               var i = du.test_arg or else 0
                toolcontext.info("Execute doc-unit {du.full_name} in {file} {i}", 1)
                var clock = new Clock
                var res2 = toolcontext.safe_exec("{file.to_program_name}.bin {i} >'{file}.out1' 2>&1 </dev/null")
@@ -209,41 +223,45 @@ class NitUnitExecutor
                end
        end
 
-       # Executes a single doc-unit in its own program.
-       # Used for docunits larger than a single block of code (with modules, classes, functions etc.)
-       fun test_single_docunit(du: DocUnit)
+       # Produce a single unit file for the docunit `du`.
+       fun generate_single_docunit(du: DocUnit): String
        do
                cpt += 1
                var file = "{prefix}-{cpt}.nit"
 
-               toolcontext.info("Execute doc-unit {du.full_name} in {file}", 1)
-
                var f
                f = create_unitfile(file)
                f.write(du.block)
                f.close
 
+               du.test_file = file
+               return file
+       end
+
+       # Executes a single doc-unit in its own program.
+       # Used for docunits larger than a single block of code (with modules, classes, functions etc.)
+       fun test_single_docunit(du: DocUnit)
+       do
+               var file = generate_single_docunit(du)
+
+               toolcontext.info("Compile doc-unit {du.full_name} in {file}", 1)
+
                if toolcontext.opt_noact.value then return
 
                var res = compile_unitfile(file)
-               var res2 = 0
-               if res == 0 then
-                       var clock = new Clock
-                       res2 = toolcontext.safe_exec("{file.to_program_name}.bin >'{file}.out1' 2>&1 </dev/null")
-                       if not toolcontext.opt_no_time.value then du.real_time = clock.total
-                       du.was_exec = true
-               end
-
                var content = "{file}.out1".to_path.read_all
                du.raw_output = content
 
+               du.test_file = file
+
                if res != 0 then
                        du.error = "Compilation error in {file}"
                        toolcontext.modelbuilder.failed_entities += 1
-               else if res2 != 0 then
-                       du.error = "Runtime error in {file}"
-                       toolcontext.modelbuilder.failed_entities += 1
+                       return
                end
+
+               du.is_compiled = true
+               execute_simple_docunit(du)
        end
 
        # Create and fill the header of a unit file `file`.
@@ -256,6 +274,7 @@ class NitUnitExecutor
        # `file` should be a valid filepath for a Nit source file.
        private fun create_unitfile(file: String): Writer
        do
+               var mmodule = self.mmodule
                var dir = file.dirname
                if dir != "" then dir.mkdir
                var f
@@ -269,33 +288,80 @@ class NitUnitExecutor
                return f
        end
 
-       # Compile an unit file and return the compiler return code
+       # Compile a unit file and return the compiler return code
        #
        # Can terminate the program if the compiler is not found
        private fun compile_unitfile(file: String): Int
        do
+               var mmodule = self.mmodule
                var nitc = toolcontext.find_nitc
                var opts = new Array[String]
                if mmodule != null then
-                       opts.add "-I {mmodule.filepath.dirname}"
+                       # FIXME playing this way with the include dir is not safe nor robust
+                       opts.add "-I {mmodule.filepath.as(not null).dirname}"
                end
                var cmd = "{nitc} --ignore-visibility --no-color -q '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
                var res = toolcontext.safe_exec(cmd)
                return res
        end
+
+       # Compile a unit file and return the compiler return code
+       #
+       # Can terminate the program if the compiler is not found
+       private fun compile_single_docunits(dus: Array[DocUnit]): Int
+       do
+               # Generate all unitfiles
+               var files = new Array[String]
+               for du in dus do
+                       files.add generate_single_docunit(du)
+               end
+
+               if files.is_empty then return 0
+
+               toolcontext.info("Compile {dus.length} single(s) doc-unit(s) at once", 1)
+
+               # Mass compile them
+               var nitc = toolcontext.find_nitc
+               var opts = new Array[String]
+               if mmodule != null then
+                       # FIXME playing this way with the include dir is not safe nor robust
+                       opts.add "-I {mmodule.filepath.dirname}"
+               end
+               var cmd = "{nitc} --ignore-visibility --no-color -q '{files.join("' '")}' {opts.join(" ")} > '{prefix}.out1' 2>&1 </dev/null --dir {prefix.dirname}"
+               var res = toolcontext.safe_exec(cmd)
+               if res != 0 then
+                       # Mass compilation failure
+                       return res
+               end
+
+               # Rename each file into it expected binary name
+               for du in dus do
+                       var f = du.test_file.as(not null)
+                       toolcontext.safe_exec("mv '{f.strip_extension(".nit")}' '{f}.bin'")
+                       du.is_compiled = true
+               end
+
+               return res
+       end
 end
 
-private class NitunitDecorator
-       super HTMLDecorator
+private class NitunitMdVisitor
+       super MdVisitor
 
        var executor: NitUnitExecutor
 
-       redef fun add_code(v, block) do
-               var code = block.raw_content
-               var meta = block.meta or else "nit"
+       redef fun visit(node) do node.accept_nitunit(self)
+
+       fun parse_code(block: MdCodeBlock) do
+               var code = block.literal
+               if code == null then return
+
+               var meta = block.info or else "nit"
                # Do not try to test non-nit code.
                if meta != "nit" then return
+
                # Try to parse code blocks
+               var executor = self.executor
                var ast = executor.toolcontext.parse_something(code)
 
                var mdoc = executor.mdoc
@@ -306,12 +372,12 @@ private class NitunitDecorator
 
                # The location is computed according to the starts of the mdoc and the block
                # Note, the following assumes that all the comments of the mdoc are correctly aligned.
-               var loc = block.block.location
+               var loc = block.location
                var line_offset = loc.line_start + mdoc.location.line_start - 2
                var column_offset = loc.column_start + mdoc.location.column_start
                # Hack to handle precise location in blocks
                # TODO remove when markdown is more reliable
-               if block isa BlockFence then
+               if block isa MdFencedCodeBlock then
                        # Skip the starting fence
                        line_offset += 1
                else
@@ -365,8 +431,7 @@ private class NitunitDecorator
        end
 
        # Return and register a new empty docunit
-       fun new_docunit: DocUnit
-       do
+       fun new_docunit: DocUnit do
                var mdoc = executor.mdoc
                assert mdoc != null
 
@@ -384,6 +449,14 @@ private class NitunitDecorator
        end
 end
 
+redef class MdNode
+       private fun accept_nitunit(v: NitunitMdVisitor) do visit_all(v)
+end
+
+redef class MdCodeBlock
+       redef fun accept_nitunit(v) do v.parse_code(self)
+end
+
 # A unit-test extracted from some documentation.
 #
 # A docunit is extracted from the code-blocks of mdocs.
@@ -403,6 +476,9 @@ class DocUnit
        # See `test_arg` that is used to distinguish them
        var test_file: nullable String = null
 
+       #  Was `test_file` successfully compiled?
+       var is_compiled = false
+
        # The command-line argument to use when executing the test, if any.
        var test_arg: nullable Int = null
 
@@ -450,10 +526,13 @@ class DocUnit
        fun real_location(ast_location: Location): Location
        do
                var mdoc = self.mdoc
-               var res = new Location(mdoc.location.file, lines[ast_location.line_start-1],
+
+               var res = new Location(mdoc.location.file,
+                       lines[ast_location.line_start-1],
                        lines[ast_location.line_end-1],
                        columns[ast_location.line_start-1] + ast_location.column_start,
                        columns[ast_location.line_end-1] + ast_location.column_end)
+
                return res
        end
 
@@ -578,7 +657,7 @@ redef class ModelBuilder
        fun test_mdoc(mdoc: MDoc): HTMLTag
        do
                var ts = new HTMLTag("testsuite")
-               var file = mdoc.location.file.filename
+               var file = mdoc.location.file.as(not null).filename
 
                toolcontext.info("nitunit: doc-unit file {file}", 2)
 
index 2580d95..04538f0 100644 (file)
@@ -21,9 +21,12 @@ import model::model_collect
 # UML model builder.
 class UMLModel
 
-       # Model view
-       var view: ModelView
+       # Model to access mentities
+       var model: Model
 
        # Main module used for linearization.
        var mainmodule: MModule
+
+       # Filters to apply on model if any
+       var filter: nullable ModelFilter
 end
index ee7f360..5dfdfd1 100644 (file)
@@ -35,7 +35,7 @@ redef class UMLModel
                                        fontname = "Bitstream Vera Sans"
                                        fontsize = 8
                                ]\n"""
-               for mclass in view.mclasses do
+               for mclass in model.collect_mclasses(filter) do
                        tpl.add mclass.tpl_class(self)
                        tpl.add "\n"
                end
@@ -72,7 +72,7 @@ redef class MClass
                        t.add "]"
                end
                t.add "|"
-               var props = collect_intro_mproperties(model.view)
+               var props = collect_intro_mproperties(model.filter)
                for i in props do
                        if not i isa MAttribute then continue
                        t.add i.tpl_class(model)
@@ -87,7 +87,7 @@ redef class MClass
                t.add "\}\"\n]\n"
                var g = in_hierarchy(model.mainmodule).direct_greaters
                for i in g do
-                       if not model.view.accept_mentity(i) then continue
+                       if not model.filter.accept_mentity(i) then continue
                        t.add "{i.name} -> {name} [dir=back"
                        if i.kind == interface_kind then
                                t.add " arrowtail=open style=dashed"
index 19726ed..d8804e6 100644 (file)
@@ -52,7 +52,7 @@ redef class MModule
                t.add "subgraph cluster{name} \{\n"
                t.add "label = \"{name}\"\n"
                for i in mclassdefs do
-                       if not model.view.accept_mentity(i) then continue
+                       if not model.filter.accept_mentity(i) then continue
                        t.add i.tpl_module(model)
                end
                t.add "\}\n"
@@ -96,14 +96,14 @@ redef class MClassDef
                t.add "|"
                for i in mpropdefs do
                        if not i isa MAttributeDef then continue
-                       if not model.view.accept_mentity(i) then continue
+                       if not model.filter.accept_mentity(i) then continue
                        t.add i.tpl_module(model)
                        t.add "\\l"
                end
                t.add "|"
                for i in mpropdefs do
                        if not i isa MMethodDef then continue
-                       if not model.view.accept_mentity(i) then continue
+                       if not model.filter.accept_mentity(i) then continue
                        t.add i.tpl_module(model)
                        t.add "\\l"
                end
index 42fc47a..cb39962 100644 (file)
@@ -8,7 +8,7 @@ ui_test
 readline
 postgres
 nitweb
-nitpm_arg3
+nitpm_args3
 langannot
 test_nitcorn
 test_annot_pkgconfig
index e08c0ad..7b99224 100644 (file)
@@ -3,6 +3,7 @@ cocoa_message_box
 hello_cocoa
 hello_ios
 test_platform_ios
+test_platform_android
 mpi
 emscripten
 neo_doxygen
@@ -10,3 +11,69 @@ neo4j
 mongo
 pernicious_numbers
 frankuchredux
+base_autocast
+base_covar_int_alt5
+base_div_by_zero
+shootout_mandelbrot_args1
+test_binary
+test_curl
+test_ffi_java
+test_ffi_objc_types_and_callbacks
+test_fix_int
+test_glsl_validation
+test_json_static
+test_jvm
+test_kill_process
+test_msgpack_deserialization
+test_nitcorn
+test_path_args1
+test_postgres
+test_read_all_args1
+test_regex_check
+test_signals
+test_stream_poll
+nitc
+nitls_args3
+nitmetrics_args3
+nitpm_args
+nitsmells_args
+nitunit_args
+nitvm
+nitweb
+test_highlight_args1
+test_neo
+test_loader_args2
+test_loader_args5
+montecarlo
+catalan_numbers
+count_the_coins
+fibonacci_word
+first_letter_last_letter
+curl_http
+nlp_index
+drop_privileges
+concurrent_array_and_barrier
+jointask_example
+socket_client
+socket_server
+socket_simple_server
+fannkuchredux
+mandelbrot
+thread_ring
+htcpcp_server
+simple_file_server
+test_restful_annot
+nitin
+nitiwiki_args1
+nitiwiki_args2
+test_annot_pkgconfig_alt
+test_gtk
+nitlight_as_a_service
+curl_rest
+lang_annot
+opengles2_hello_triangle
+nlp_server
+ui_test
+restful_annot
+langannot
+simple_simulation
index c643d3d..e18f76f 100644 (file)
@@ -1,4 +1,4 @@
-module_1.nit -d $WRITE
-base_attr_nullable.nit -d $WRITE
---private base_attr_nullable.nit --no-attributes -d $WRITE
---no-render --test test_prog -d $WRITE
+--test module_1.nit -d $WRITE
+--test base_attr_nullable.nit -d $WRITE
+--test --private base_attr_nullable.nit --no-attributes -d $WRITE
+--test --no-render test_prog -d $WRITE
index 7a451c4..0d24e60 100644 (file)
@@ -44,3 +44,4 @@ test_rubix_visual
 test_csv
 repeating_key_xor_solve
 nitpm
+nitdoc
index d346e2c..697b17e 100644 (file)
@@ -47,3 +47,4 @@ test_explain_assert
 base_notnull_lit_alt2
 assertions
 nitpm
+nitdoc
index d532535..46e2b1a 100644 (file)
@@ -6,8 +6,8 @@
 ../lib/core/kernel.nit:431,1--486,3: Error: `kernel$Numeric` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:492,1--515,3: Error: `kernel$Bool` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
 ../lib/core/kernel.nit:517,1--599,3: Error: `kernel$Float` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:601,1--705,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:707,1--885,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:887,1--1056,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1058,1--1075,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1077,1--1086,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:601,1--700,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:702,1--883,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:885,1--1064,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1066,1--1083,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1085,1--1094,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
diff --git a/tests/sav/libevent_test.res b/tests/sav/libevent_test.res
new file mode 100644 (file)
index 0000000..b0f29bd
--- /dev/null
@@ -0,0 +1,8 @@
+[Server] New client: 127.0.0.1
+[Server] Write: Hi
+Hi
+[Server] Read: Hello TCP
+[Server] New client: Abstract UNIX domain socket
+[Server] Write: Hi
+Hi
+[Server] Read: Hello UNIX
index e131b2e..5bdd4bf 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723)
 11
 21
 31
index e131b2e..5bdd4bf 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723)
 11
 21
 31
index e131b2e..5bdd4bf 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723)
 11
 21
 31
index 5fea655..a7326d6 100644 (file)
@@ -1,37 +1,39 @@
-Empty README for group `module_1` (readme-warning)
-Empty README for group `module_0` (readme-warning)
-Errors: 0. Warnings: 2.
-class_module_95d0-__Int.html
-class_module_95d0-__Object.html
-class_module_95d0-__Sys.html
-class_module_95d1-__A.html
-class_module_95d1-__B.html
+Parsing code...
+Generating documentation pages...
+Documentation produced in `out/nitdoc_args1.write`
+Generated 22/22 pages
+ PageHome: 1
+ PageMPackage: 2
+ PageMGroup: 2
+ PageMModule: 2
+ PageMClass: 5
+ PageMProperty: 10
+ PagePerson: 0
+ PageTag: 0
+class_module_95d0_58d_58dInt.html
+class_module_95d0_58d_58dObject.html
+class_module_95d0_58d_58dSys.html
+class_module_95d1_58d_58dA.html
+class_module_95d1_58d_58dB.html
 css/
-dep_class_module_95d0-__Int.dot
-dep_class_module_95d0-__Object.dot
-dep_class_module_95d0-__Sys.dot
-dep_class_module_95d1-__A.dot
-dep_class_module_95d1-__B.dot
-dep_module_module_95d0-.dot
-dep_module_module_95d1-.dot
-group_module_95d0.html
-group_module_95d1.html
+group_module_95d0_62d.html
+group_module_95d1_62d.html
 index.html
 js/
 less/
-module_module_95d0-.html
-module_module_95d1-.html
-property_module_95d0-__Object__init.html
-property_module_95d0-__Object__output.html
-property_module_95d0-__Object__print.html
-property_module_95d0-__Sys__main.html
-property_module_95d1-__A__a1.html
-property_module_95d1-__A__a12.html
-property_module_95d1-__A__a123.html
-property_module_95d1-__A__a13.html
-property_module_95d1-__B__all2.html
-property_module_95d1-__B__all25.html
+module_module_95d0_58d_58dmodule_95d0.html
+module_module_95d1_58d_58dmodule_95d1.html
+package_module_95d0.html
+package_module_95d1.html
+property_module_95d0_58d_58dObject_58d_58dinit.html
+property_module_95d0_58d_58dObject_58d_58doutput.html
+property_module_95d0_58d_58dObject_58d_58dprint.html
+property_module_95d0_58d_58dSys_58d_58dmain.html
+property_module_95d1_58d_58dA_58d_58da1.html
+property_module_95d1_58d_58dA_58d_58da12.html
+property_module_95d1_58d_58dA_58d_58da123.html
+property_module_95d1_58d_58dA_58d_58da13.html
+property_module_95d1_58d_58dB_58d_58dall2.html
+property_module_95d1_58d_58dB_58d_58dall25.html
 quicksearch-list.js
-resources/
-search.html
 vendors/
index fd347db..268190c 100644 (file)
@@ -1,44 +1,45 @@
-Empty README for group `base_attr_nullable` (readme-warning)
-Errors: 0. Warnings: 1.
-class_base_attr_nullable-__Bar.html
-class_base_attr_nullable-__Bool.html
-class_base_attr_nullable-__Foo.html
-class_base_attr_nullable-__Int.html
-class_base_attr_nullable-__Integer.html
-class_base_attr_nullable-__Object.html
-class_base_attr_nullable-__Sys.html
+Parsing code...
+Generating documentation pages...
+Documentation produced in `out/nitdoc_args2.write`
+Generated 28/28 pages
+ PageHome: 1
+ PageMPackage: 1
+ PageMGroup: 1
+ PageMModule: 1
+ PageMClass: 7
+ PageMProperty: 17
+ PagePerson: 0
+ PageTag: 0
+class_base_attr_nullable_58d_58dBar.html
+class_base_attr_nullable_58d_58dBool.html
+class_base_attr_nullable_58d_58dFoo.html
+class_base_attr_nullable_58d_58dInt.html
+class_base_attr_nullable_58d_58dInteger.html
+class_base_attr_nullable_58d_58dObject.html
+class_base_attr_nullable_58d_58dSys.html
 css/
-dep_class_base_attr_nullable-__Bar.dot
-dep_class_base_attr_nullable-__Bool.dot
-dep_class_base_attr_nullable-__Foo.dot
-dep_class_base_attr_nullable-__Int.dot
-dep_class_base_attr_nullable-__Integer.dot
-dep_class_base_attr_nullable-__Object.dot
-dep_class_base_attr_nullable-__Sys.dot
-dep_module_base_attr_nullable-.dot
-group_base_attr_nullable.html
+group_base_attr_nullable_62d.html
 index.html
 js/
 less/
-module_base_attr_nullable-.html
-property_base_attr_nullable-__Bar__a3.html
-property_base_attr_nullable-__Bar__a3_61d.html
-property_base_attr_nullable-__Foo__a1.html
-property_base_attr_nullable-__Foo__a1_61d.html
-property_base_attr_nullable-__Foo__a2.html
-property_base_attr_nullable-__Foo__a2_61d.html
-property_base_attr_nullable-__Foo__nop.html
-property_base_attr_nullable-__Foo__run.html
-property_base_attr_nullable-__Foo__run_other.html
-property_base_attr_nullable-__Int___43d.html
-property_base_attr_nullable-__Int__output.html
-property_base_attr_nullable-__Integer__init.html
-property_base_attr_nullable-__Integer__output.html
-property_base_attr_nullable-__Integer__val.html
-property_base_attr_nullable-__Integer__val_61d.html
-property_base_attr_nullable-__Object__init.html
-property_base_attr_nullable-__Sys__main.html
+module_base_attr_nullable_58d_58dbase_attr_nullable.html
+package_base_attr_nullable.html
+property_base_attr_nullable_58d_58dBar_58d_58da3.html
+property_base_attr_nullable_58d_58dBar_58d_58da3_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58da1.html
+property_base_attr_nullable_58d_58dFoo_58d_58da1_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58da2.html
+property_base_attr_nullable_58d_58dFoo_58d_58da2_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58dnop.html
+property_base_attr_nullable_58d_58dFoo_58d_58drun.html
+property_base_attr_nullable_58d_58dFoo_58d_58drun_other.html
+property_base_attr_nullable_58d_58dInt_58d_58d_43d.html
+property_base_attr_nullable_58d_58dInt_58d_58doutput.html
+property_base_attr_nullable_58d_58dInteger_58d_58dinit.html
+property_base_attr_nullable_58d_58dInteger_58d_58doutput.html
+property_base_attr_nullable_58d_58dInteger_58d_58dval.html
+property_base_attr_nullable_58d_58dInteger_58d_58dval_61d.html
+property_base_attr_nullable_58d_58dObject_58d_58dinit.html
+property_base_attr_nullable_58d_58dSys_58d_58dmain.html
 quicksearch-list.js
-resources/
-search.html
 vendors/
index fd347db..105d27c 100644 (file)
@@ -1,44 +1,45 @@
-Empty README for group `base_attr_nullable` (readme-warning)
-Errors: 0. Warnings: 1.
-class_base_attr_nullable-__Bar.html
-class_base_attr_nullable-__Bool.html
-class_base_attr_nullable-__Foo.html
-class_base_attr_nullable-__Int.html
-class_base_attr_nullable-__Integer.html
-class_base_attr_nullable-__Object.html
-class_base_attr_nullable-__Sys.html
+Parsing code...
+Generating documentation pages...
+Documentation produced in `out/nitdoc_args3.write`
+Generated 28/28 pages
+ PageHome: 1
+ PageMPackage: 1
+ PageMGroup: 1
+ PageMModule: 1
+ PageMClass: 7
+ PageMProperty: 17
+ PagePerson: 0
+ PageTag: 0
+class_base_attr_nullable_58d_58dBar.html
+class_base_attr_nullable_58d_58dBool.html
+class_base_attr_nullable_58d_58dFoo.html
+class_base_attr_nullable_58d_58dInt.html
+class_base_attr_nullable_58d_58dInteger.html
+class_base_attr_nullable_58d_58dObject.html
+class_base_attr_nullable_58d_58dSys.html
 css/
-dep_class_base_attr_nullable-__Bar.dot
-dep_class_base_attr_nullable-__Bool.dot
-dep_class_base_attr_nullable-__Foo.dot
-dep_class_base_attr_nullable-__Int.dot
-dep_class_base_attr_nullable-__Integer.dot
-dep_class_base_attr_nullable-__Object.dot
-dep_class_base_attr_nullable-__Sys.dot
-dep_module_base_attr_nullable-.dot
-group_base_attr_nullable.html
+group_base_attr_nullable_62d.html
 index.html
 js/
 less/
-module_base_attr_nullable-.html
-property_base_attr_nullable-__Bar__a3.html
-property_base_attr_nullable-__Bar__a3_61d.html
-property_base_attr_nullable-__Foo__a1.html
-property_base_attr_nullable-__Foo__a1_61d.html
-property_base_attr_nullable-__Foo__a2.html
-property_base_attr_nullable-__Foo__a2_61d.html
-property_base_attr_nullable-__Foo__nop.html
-property_base_attr_nullable-__Foo__run.html
-property_base_attr_nullable-__Foo__run_other.html
-property_base_attr_nullable-__Int___43d.html
-property_base_attr_nullable-__Int__output.html
-property_base_attr_nullable-__Integer__init.html
-property_base_attr_nullable-__Integer__output.html
-property_base_attr_nullable-__Integer__val.html
-property_base_attr_nullable-__Integer__val_61d.html
-property_base_attr_nullable-__Object__init.html
-property_base_attr_nullable-__Sys__main.html
+module_base_attr_nullable_58d_58dbase_attr_nullable.html
+package_base_attr_nullable.html
+property_base_attr_nullable_58d_58dBar_58d_58da3.html
+property_base_attr_nullable_58d_58dBar_58d_58da3_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58da1.html
+property_base_attr_nullable_58d_58dFoo_58d_58da1_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58da2.html
+property_base_attr_nullable_58d_58dFoo_58d_58da2_61d.html
+property_base_attr_nullable_58d_58dFoo_58d_58dnop.html
+property_base_attr_nullable_58d_58dFoo_58d_58drun.html
+property_base_attr_nullable_58d_58dFoo_58d_58drun_other.html
+property_base_attr_nullable_58d_58dInt_58d_58d_43d.html
+property_base_attr_nullable_58d_58dInt_58d_58doutput.html
+property_base_attr_nullable_58d_58dInteger_58d_58dinit.html
+property_base_attr_nullable_58d_58dInteger_58d_58doutput.html
+property_base_attr_nullable_58d_58dInteger_58d_58dval.html
+property_base_attr_nullable_58d_58dInteger_58d_58dval_61d.html
+property_base_attr_nullable_58d_58dObject_58d_58dinit.html
+property_base_attr_nullable_58d_58dSys_58d_58dmain.html
 quicksearch-list.js
-resources/
-search.html
 vendors/
index e764a49..3be4a55 100644 (file)
-Empty README for group `examples` (readme-warning)
-Empty README for group `man` (readme-warning)
-Empty README for group `tests` (readme-warning)
-Empty README for group `excluded` (readme-warning)
-Errors: 0. Warnings: 4.
-MGroupPage excluded
-       # excluded.section
-               ## excluded.intro
-               ## excluded.concerns
-               ## excluded.concern
-               ## excluded.concern
-               ## excluded-.concern
-                       ### excluded-.definition
-                               #### excluded-.intros_redefs
-                                       ##### list.group
-                                               ###### excluded-.intros
-                                               ###### excluded-.redefs
-
-MModulePage excluded
-       # excluded.section
-               ## excluded-.intro
-               ## excluded-.importation
-                       ### excluded-.graph
-                       ### list.group
-                               #### excluded-.imports
-                               #### excluded-.clients
-
-OverviewPage Overview
-       # home.article
-               ## packages.section
-                       ### excluded.definition
-                       ### test_prog.definition
-
-ReadmePage excluded
-
-ReadmePage test_prog
-       # mdarticle-0
-
-ReadmePage examples
-
-ReadmePage game
-       # mdarticle-0
-
-ReadmePage man
-
-ReadmePage platform
-       # mdarticle-0
-
-ReadmePage rpg
-       # mdarticle-0
-
-ReadmePage tests
-
-SearchPage Index
-       # index.article
-
-MGroupPage test_prog
-       # test_prog.section
-               ## test_prog.intro
-               ## test_prog.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog-.concern
-                       ### test_prog-.definition
-                               #### test_prog-.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog-.intros
-                                               ###### test_prog-.redefs
-
-MModulePage test_prog
-       # test_prog.section
-               ## test_prog-.intro
-               ## test_prog-.importation
-                       ### test_prog-.graph
-                       ### list.group
-                               #### test_prog-.imports
-                               #### test_prog-.clients
-               ## test_prog-.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog-.concern
-                       ### test_prog-__Starter.definition-list
-                               #### test_prog-__Starter.definition
-                                       ##### test_prog-__Starter.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog-__Starter.intros
-                                                       ####### test_prog-__Starter.redefs
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Sys.definition-list
-                               #### test_prog__platform-__Sys.definition
-                               #### test_prog-__Sys.definition
-                                       ##### test_prog-__Sys.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog-__Sys.intros
-                                                       ####### test_prog-__Sys.redefs
-
-MClassPage Starter
-       # Starter.section
-               ## test_prog-__Starter.intro
-               ## test_prog-__Starter.inheritance
-                       ### test_prog-__Starter.graph
-                       ### list.group
-                               #### test_prog-__Starter.parents
-                               #### test_prog-__Starter.ancestors
-                               #### test_prog-__Starter.children
-                               #### test_prog-__Starter.descendants
-               ## test_prog-__Starter.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog-__Starter.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog-.concern
-                       ### test_prog-__Starter__start.definition
-
-MPropertyPage start
-       # start.section
-               ## test_prog-__Starter__start.intro
-
-MGroupPage examples
-       # examples.section
-               ## test_prog__examples.intro
-               ## test_prog__examples.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-.definition
-                               #### test_prog__examples-.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__examples-.intros
-                                               ###### test_prog__examples-.redefs
-
-MModulePage game_examples
-       # game_examples.section
-               ## test_prog__examples-.intro
-               ## test_prog__examples-.importation
-                       ### test_prog__examples-.graph
-                       ### list.group
-                               #### test_prog__examples-.imports
-                               #### test_prog__examples-.clients
-               ## test_prog__examples-.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame.definition-list
-                               #### test_prog__examples-__MyGame.definition
-                                       ##### test_prog__examples-__MyGame.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__examples-__MyGame.intros
-                                                       ####### test_prog__examples-__MyGame.redefs
-
-MClassPage MyGame
-       # MyGame.section
-               ## test_prog__examples-__MyGame.intro
-               ## test_prog__examples-__MyGame.inheritance
-                       ### test_prog__examples-__MyGame.graph
-                       ### list.group
-                               #### test_prog__examples-__MyGame.parents
-                               #### test_prog__examples-__MyGame.ancestors
-                               #### test_prog__examples-__MyGame.children
-                               #### test_prog__examples-__MyGame.descendants
-               ## test_prog__examples-__MyGame.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__examples-__MyGame.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__computer_characters.definition
-                               #### test_prog__examples-__MyGame__computer_characters.lin
-                       ### test_prog__examples-__MyGame__computer_characters_61d.definition
-                       ### test_prog__examples-__MyGame__pause_game.definition
-                               #### test_prog__examples-__MyGame__pause_game.lin
-                       ### test_prog__examples-__MyGame__player_characters.definition
-                               #### test_prog__examples-__MyGame__player_characters.lin
-                       ### test_prog__examples-__MyGame__player_characters_61d.definition
-                       ### test_prog__examples-__MyGame__start_game.definition
-                               #### test_prog__examples-__MyGame__start_game.lin
-                       ### test_prog__examples-__MyGame__stop_game.definition
-                               #### test_prog__examples-__MyGame__stop_game.lin
-
-MPropertyPage computer_characters=
-       # computer_characters=.section
-               ## test_prog__examples-__MyGame__computer_characters_61d.intro
-
-MPropertyPage player_characters=
-       # player_characters=.section
-               ## test_prog__examples-__MyGame__player_characters_61d.intro
-
-MGroupPage game
-       # game.section
-               ## test_prog__game.intro
-               ## test_prog__game.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__game.concern
-               ## test_prog__game-.concern
-                       ### test_prog__game-.definition
-                               #### test_prog__game-.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__game-.intros
-                                               ###### test_prog__game-.redefs
-
-MModulePage game
-       # game.section
-               ## test_prog__game-.intro
-               ## test_prog__game-.importation
-                       ### test_prog__game-.graph
-                       ### list.group
-                               #### test_prog__game-.imports
-                               #### test_prog__game-.clients
-               ## test_prog__game-.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__game.concern
-               ## test_prog__game-.concern
-                       ### test_prog__game-__Game.definition-list
-                               #### test_prog__game-__Game.definition
-                                       ##### test_prog__game-__Game.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__game-__Game.intros
-                                                       ####### test_prog__game-__Game.redefs
-
-MClassPage Game
-       # Game.section
-               ## test_prog__game-__Game.intro
-               ## test_prog__game-__Game.inheritance
-                       ### test_prog__game-__Game.graph
-                       ### list.group
-                               #### test_prog__game-__Game.parents
-                               #### test_prog__game-__Game.ancestors
-                               #### test_prog__game-__Game.children
-                               #### test_prog__game-__Game.descendants
-               ## test_prog__game-__Game.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__game-__Game.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__game.concern
-               ## test_prog__game-.concern
-                       ### test_prog__game-__Game__computer_characters.definition
-                       ### test_prog__game-__Game__pause_game.definition
-                       ### test_prog__game-__Game__player_characters.definition
-                       ### test_prog__game-__Game__start_game.definition
-                       ### test_prog__game-__Game__stop_game.definition
-
-MPropertyPage computer_characters
-       # computer_characters.section
-               ## test_prog__game-__Game__computer_characters.intro
-               ## test_prog__game-__Game__computer_characters.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__computer_characters.definition
-
-MPropertyPage pause_game
-       # pause_game.section
-               ## test_prog__game-__Game__pause_game.intro
-               ## test_prog__game-__Game__pause_game.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__pause_game.definition
-
-MPropertyPage player_characters
-       # player_characters.section
-               ## test_prog__game-__Game__player_characters.intro
-               ## test_prog__game-__Game__player_characters.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__player_characters.definition
-               ## test_prog__tests.concern
-               ## test_prog__tests-.concern
-                       ### test_prog__tests-__TestGame__player_characters.definition
-
-MPropertyPage start_game
-       # start_game.section
-               ## test_prog__game-__Game__start_game.intro
-               ## test_prog__game-__Game__start_game.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__start_game.definition
-
-MPropertyPage stop_game
-       # stop_game.section
-               ## test_prog__game-__Game__stop_game.intro
-               ## test_prog__game-__Game__stop_game.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__examples.concern
-               ## test_prog__examples-.concern
-                       ### test_prog__examples-__MyGame__stop_game.definition
-
-MGroupPage man
-       # man.section
-               ## test_prog__man.intro
-
-MGroupPage platform
-       # platform.section
-               ## test_prog__platform.intro
-               ## test_prog__platform.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-.definition
-                               #### test_prog__platform-.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__platform-.intros
-                                               ###### test_prog__platform-.redefs
-
-MModulePage platform
-       # platform.section
-               ## test_prog__platform-.intro
-               ## test_prog__platform-.importation
-                       ### test_prog__platform-.graph
-                       ### list.group
-                               #### test_prog__platform-.imports
-                               #### test_prog__platform-.clients
-               ## test_prog__platform-.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Bool.definition-list
-                               #### test_prog__platform-__Bool.definition
-                                       ##### test_prog__platform-__Bool.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__Bool.intros
-                                                       ####### test_prog__platform-__Bool.redefs
-                       ### test_prog__platform-__Float.definition-list
-                               #### test_prog__platform-__Float.definition
-                                       ##### test_prog__platform-__Float.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__Float.intros
-                                                       ####### test_prog__platform-__Float.redefs
-                       ### test_prog__platform-__Int.definition-list
-                               #### test_prog__platform-__Int.definition
-                                       ##### test_prog__platform-__Int.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__Int.intros
-                                                       ####### test_prog__platform-__Int.redefs
-                       ### test_prog__platform-__List.definition-list
-                               #### test_prog__platform-__List.definition
-                                       ##### test_prog__platform-__List.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__List.intros
-                                                       ####### test_prog__platform-__List.redefs
-                       ### test_prog__platform-__Object.definition-list
-                               #### test_prog__platform-__Object.definition
-                                       ##### test_prog__platform-__Object.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__Object.intros
-                                                       ####### test_prog__platform-__Object.redefs
-                       ### test_prog__platform-__String.definition-list
-                               #### test_prog__platform-__String.definition
-                                       ##### test_prog__platform-__String.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__String.intros
-                                                       ####### test_prog__platform-__String.redefs
-                       ### test_prog__platform-__Sys.definition-list
-                               #### test_prog__platform-__Sys.definition
-                                       ##### test_prog__platform-__Sys.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__platform-__Sys.intros
-                                                       ####### test_prog__platform-__Sys.redefs
-
-MClassPage Bool
-       # Bool.section
-               ## test_prog__platform-__Bool.intro
-               ## test_prog__platform-__Bool.inheritance
-                       ### test_prog__platform-__Bool.graph
-                       ### list.group
-                               #### test_prog__platform-__Bool.parents
-                               #### test_prog__platform-__Bool.ancestors
-                               #### test_prog__platform-__Bool.children
-                               #### test_prog__platform-__Bool.descendants
-
-MClassPage Float
-       # Float.section
-               ## test_prog__platform-__Float.intro
-               ## test_prog__platform-__Float.inheritance
-                       ### test_prog__platform-__Float.graph
-                       ### list.group
-                               #### test_prog__platform-__Float.parents
-                               #### test_prog__platform-__Float.ancestors
-                               #### test_prog__platform-__Float.children
-                               #### test_prog__platform-__Float.descendants
-               ## test_prog__platform-__Float.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__platform-__Float.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Float___42d.definition
-                       ### test_prog__platform-__Float___43d.definition
-                       ### test_prog__platform-__Float___45d.definition
-                       ### test_prog__platform-__Float___47d.definition
-                       ### test_prog__platform-__Float___62d.definition
-
-MPropertyPage *
-       # *.section
-               ## test_prog__platform-__Float___42d.intro
-
-MPropertyPage +
-       # +.section
-               ## test_prog__platform-__Float___43d.intro
-
-MPropertyPage -
-       # -.section
-               ## test_prog__platform-__Float___45d.intro
-
-MPropertyPage &#47;
-       # &#47;.section
-               ## test_prog__platform-__Float___47d.intro
-
-MPropertyPage &gt;
-       # &gt;.section
-               ## test_prog__platform-__Float___62d.intro
-
-MClassPage Int
-       # Int.section
-               ## test_prog__platform-__Int.intro
-               ## test_prog__platform-__Int.inheritance
-                       ### test_prog__platform-__Int.graph
-                       ### list.group
-                               #### test_prog__platform-__Int.parents
-                               #### test_prog__platform-__Int.ancestors
-                               #### test_prog__platform-__Int.children
-                               #### test_prog__platform-__Int.descendants
-               ## test_prog__platform-__Int.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__platform-__Int.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Int___42d.definition
-                       ### test_prog__platform-__Int___43d.definition
-                       ### test_prog__platform-__Int___45d.definition
-                       ### test_prog__platform-__Int___47d.definition
-                       ### test_prog__platform-__Int___62d.definition
-                       ### test_prog__platform-__Int__to_f.definition
-                       ### test_prog__platform-__Int__unary_32d_45d.definition
-
-MPropertyPage *
-       # *.section
-               ## test_prog__platform-__Int___42d.intro
-
-MPropertyPage +
-       # +.section
-               ## test_prog__platform-__Int___43d.intro
-
-MPropertyPage -
-       # -.section
-               ## test_prog__platform-__Int___45d.intro
-
-MPropertyPage &#47;
-       # &#47;.section
-               ## test_prog__platform-__Int___47d.intro
-
-MPropertyPage &gt;
-       # &gt;.section
-               ## test_prog__platform-__Int___62d.intro
-
-MPropertyPage to_f
-       # to_f.section
-               ## test_prog__platform-__Int__to_f.intro
-
-MPropertyPage unary -
-       # unary -.section
-               ## test_prog__platform-__Int__unary_32d_45d.intro
-
-MClassPage List
-       # List.section
-               ## test_prog__platform-__List.intro
-               ## test_prog__platform-__List.inheritance
-                       ### test_prog__platform-__List.graph
-                       ### list.group
-                               #### test_prog__platform-__List.parents
-                               #### test_prog__platform-__List.ancestors
-                               #### test_prog__platform-__List.children
-                               #### test_prog__platform-__List.descendants
-
-MClassPage Object
-       # Object.section
-               ## test_prog__platform-__Object.intro
-               ## test_prog__platform-__Object.inheritance
-                       ### test_prog__platform-__Object.graph
-                       ### list.group
-                               #### test_prog__platform-__Object.parents
-                               #### test_prog__platform-__Object.ancestors
-                               #### test_prog__platform-__Object.children
-                               #### test_prog__platform-__Object.descendants
-               ## test_prog__platform-__Object.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__platform-__Object.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Object__OTHER.definition
-                       ### test_prog__platform-__Object___33d_61d.definition
-                       ### test_prog__platform-__Object___61d_61d.definition
-
-MPropertyPage OTHER
-       # OTHER.section
-               ## test_prog__platform-__Object__OTHER.intro
-
-MPropertyPage !=
-       # !=.section
-               ## test_prog__platform-__Object___33d_61d.intro
-
-MPropertyPage ==
-       # ==.section
-               ## test_prog__platform-__Object___61d_61d.intro
-
-MPropertyPage init
-       # init.section
-               ## test_prog__platform-__Object__init.intro
-               ## test_prog__platform-__Object__init.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-                       ### test_prog__rpg__careers__Career__init.definition
-                       ### test_prog__rpg__careers__Warrior__init.definition
-                       ### test_prog__rpg__careers__Magician__init.definition
-                       ### test_prog__rpg__careers__Alcoholic__init.definition
-               ## test_prog__rpg__races.concern
-                       ### test_prog__rpg__races__Race__init.definition
-                       ### test_prog__rpg__races__Human__init.definition
-                       ### test_prog__rpg__races__Dwarf__init.definition
-                       ### test_prog__rpg__races__Elf__init.definition
-               ## test_prog__rpg__character.concern
-                       ### test_prog__rpg__character__Character__init.definition
-
-MClassPage String
-       # String.section
-               ## test_prog__platform-__String.intro
-               ## test_prog__platform-__String.inheritance
-                       ### test_prog__platform-__String.graph
-                       ### list.group
-                               #### test_prog__platform-__String.parents
-                               #### test_prog__platform-__String.ancestors
-                               #### test_prog__platform-__String.children
-                               #### test_prog__platform-__String.descendants
-
-MClassPage Sys
-       # Sys.section
-               ## test_prog__platform-__Sys.intro
-               ## test_prog__platform-__Sys.inheritance
-                       ### test_prog__platform-__Sys.graph
-                       ### list.group
-                               #### test_prog__platform-__Sys.parents
-                               #### test_prog__platform-__Sys.ancestors
-                               #### test_prog__platform-__Sys.children
-                               #### test_prog__platform-__Sys.descendants
-               ## test_prog__platform-__Sys.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__platform-__Sys.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__platform.concern
-               ## test_prog__platform-.concern
-                       ### test_prog__platform-__Sys__main.definition
-                               #### test_prog__platform-__Sys__main.lin
-               ## test_prog-.concern
-                       ### test_prog-__Sys__main.definition
-                               #### test_prog-__Sys__main.lin
-
-MPropertyPage main
-       # main.section
-               ## test_prog__platform-__Sys__main.intro
-               ## test_prog__platform-__Sys__main.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog-.concern
-                       ### test_prog-__Sys__main.definition
-
-MGroupPage rpg
-       # rpg.section
-               ## test_prog__rpg.intro
-               ## test_prog__rpg.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-                       ### test_prog__rpg__careers.definition
-                               #### test_prog__rpg__careers.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__rpg__careers.intros
-                                               ###### test_prog__rpg__careers.redefs
-               ## test_prog__rpg__races.concern
-                       ### test_prog__rpg__races.definition
-                               #### test_prog__rpg__races.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__rpg__races.intros
-                                               ###### test_prog__rpg__races.redefs
-               ## test_prog__rpg__character.concern
-                       ### test_prog__rpg__character.definition
-                               #### test_prog__rpg__character.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__rpg__character.intros
-                                               ###### test_prog__rpg__character.redefs
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat.definition
-                               #### test_prog__rpg__combat.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__rpg__combat.intros
-                                               ###### test_prog__rpg__combat.redefs
-               ## test_prog__rpg__rpg.concern
-                       ### test_prog__rpg__rpg.definition
-                               #### test_prog__rpg__rpg.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__rpg__rpg.intros
-                                               ###### test_prog__rpg__rpg.redefs
-
-MModulePage careers
-       # careers.section
-               ## test_prog__rpg__careers.intro
-               ## test_prog__rpg__careers.importation
-                       ### test_prog__rpg__careers.graph
-                       ### list.group
-                               #### test_prog__rpg__careers.imports
-                               #### test_prog__rpg__careers.clients
-               ## test_prog__rpg__careers.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-                       ### test_prog__rpg__careers__Alcoholic.definition-list
-                               #### test_prog__rpg__careers__Alcoholic.definition
-                                       ##### test_prog__rpg__careers__Alcoholic.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__careers__Alcoholic.intros
-                                                       ####### test_prog__rpg__careers__Alcoholic.redefs
-                       ### test_prog__rpg__careers__Career.definition-list
-                               #### test_prog__rpg__careers__Career.definition
-                                       ##### test_prog__rpg__careers__Career.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__careers__Career.intros
-                                                       ####### test_prog__rpg__careers__Career.redefs
-                       ### test_prog__rpg__careers__Magician.definition-list
-                               #### test_prog__rpg__careers__Magician.definition
-                                       ##### test_prog__rpg__careers__Magician.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__careers__Magician.intros
-                                                       ####### test_prog__rpg__careers__Magician.redefs
-                       ### test_prog__rpg__careers__Warrior.definition-list
-                               #### test_prog__rpg__careers__Warrior.definition
-                                       ##### test_prog__rpg__careers__Warrior.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__careers__Warrior.intros
-                                                       ####### test_prog__rpg__careers__Warrior.redefs
-
-MClassPage Alcoholic
-       # Alcoholic.section
-               ## test_prog__rpg__careers__Alcoholic.intro
-               ## test_prog__rpg__careers__Alcoholic.inheritance
-                       ### test_prog__rpg__careers__Alcoholic.graph
-                       ### list.group
-                               #### test_prog__rpg__careers__Alcoholic.parents
-                               #### test_prog__rpg__careers__Alcoholic.ancestors
-                               #### test_prog__rpg__careers__Alcoholic.children
-                               #### test_prog__rpg__careers__Alcoholic.descendants
-               ## test_prog__rpg__careers__Alcoholic.constructors
-                       ### test_prog__rpg__careers__Alcoholic__init.definition
-                               #### test_prog__rpg__careers__Alcoholic__init.lin
-               ## test_prog__rpg__careers__Alcoholic.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-
-MClassPage Career
-       # Career.section
-               ## test_prog__rpg__careers__Career.intro
-               ## test_prog__rpg__careers__Career.inheritance
-                       ### test_prog__rpg__careers__Career.graph
-                       ### list.group
-                               #### test_prog__rpg__careers__Career.parents
-                               #### test_prog__rpg__careers__Career.ancestors
-                               #### test_prog__rpg__careers__Career.children
-                               #### test_prog__rpg__careers__Career.descendants
-               ## test_prog__rpg__careers__Career.constructors
-                       ### test_prog__rpg__careers__Career__init.definition
-                               #### test_prog__rpg__careers__Career__init.lin
-               ## test_prog__rpg__careers__Career.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-                       ### test_prog__rpg__careers__Career__endurance_bonus.definition
-                       ### test_prog__rpg__careers__Career__endurance_bonus_61d.definition
-                       ### test_prog__rpg__careers__Career__intelligence_bonus.definition
-                       ### test_prog__rpg__careers__Career__intelligence_bonus_61d.definition
-                       ### test_prog__rpg__careers__Career__strength_bonus.definition
-                       ### test_prog__rpg__careers__Career__strength_bonus_61d.definition
-
-MPropertyPage endurance_bonus
-       # endurance_bonus.section
-               ## test_prog__rpg__careers__Career__endurance_bonus.intro
-
-MPropertyPage endurance_bonus=
-       # endurance_bonus=.section
-               ## test_prog__rpg__careers__Career__endurance_bonus_61d.intro
-
-MPropertyPage intelligence_bonus
-       # intelligence_bonus.section
-               ## test_prog__rpg__careers__Career__intelligence_bonus.intro
-
-MPropertyPage intelligence_bonus=
-       # intelligence_bonus=.section
-               ## test_prog__rpg__careers__Career__intelligence_bonus_61d.intro
-
-MPropertyPage strength_bonus
-       # strength_bonus.section
-               ## test_prog__rpg__careers__Career__strength_bonus.intro
-
-MPropertyPage strength_bonus=
-       # strength_bonus=.section
-               ## test_prog__rpg__careers__Career__strength_bonus_61d.intro
-
-MClassPage Magician
-       # Magician.section
-               ## test_prog__rpg__careers__Magician.intro
-               ## test_prog__rpg__careers__Magician.inheritance
-                       ### test_prog__rpg__careers__Magician.graph
-                       ### list.group
-                               #### test_prog__rpg__careers__Magician.parents
-                               #### test_prog__rpg__careers__Magician.ancestors
-                               #### test_prog__rpg__careers__Magician.children
-                               #### test_prog__rpg__careers__Magician.descendants
-               ## test_prog__rpg__careers__Magician.constructors
-                       ### test_prog__rpg__careers__Magician__init.definition
-                               #### test_prog__rpg__careers__Magician__init.lin
-               ## test_prog__rpg__careers__Magician.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-
-MClassPage Warrior
-       # Warrior.section
-               ## test_prog__rpg__careers__Warrior.intro
-               ## test_prog__rpg__careers__Warrior.inheritance
-                       ### test_prog__rpg__careers__Warrior.graph
-                       ### list.group
-                               #### test_prog__rpg__careers__Warrior.parents
-                               #### test_prog__rpg__careers__Warrior.ancestors
-                               #### test_prog__rpg__careers__Warrior.children
-                               #### test_prog__rpg__careers__Warrior.descendants
-               ## test_prog__rpg__careers__Warrior.constructors
-                       ### test_prog__rpg__careers__Warrior__init.definition
-                               #### test_prog__rpg__careers__Warrior__init.lin
-               ## test_prog__rpg__careers__Warrior.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__careers.concern
-
-MModulePage character
-       # character.section
-               ## test_prog__rpg__character.intro
-               ## test_prog__rpg__character.importation
-                       ### test_prog__rpg__character.graph
-                       ### list.group
-                               #### test_prog__rpg__character.imports
-                               #### test_prog__rpg__character.clients
-               ## test_prog__rpg__character.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__character.concern
-                       ### test_prog__rpg__character__Character.definition-list
-                               #### test_prog__rpg__character__Character.definition
-                                       ##### test_prog__rpg__character__Character.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__character__Character.intros
-                                                       ####### test_prog__rpg__character__Character.redefs
-
-MClassPage Character
-       # Character.section
-               ## test_prog__rpg__character__Character.intro
-               ## test_prog__rpg__character__Character.inheritance
-                       ### test_prog__rpg__character__Character.graph
-                       ### list.group
-                               #### test_prog__rpg__character__Character.parents
-                               #### test_prog__rpg__character__Character.ancestors
-                               #### test_prog__rpg__character__Character.children
-                               #### test_prog__rpg__character__Character.descendants
-               ## test_prog__rpg__character__Character.constructors
-                       ### test_prog__rpg__character__Character__init.definition
-                               #### test_prog__rpg__character__Character__init.lin
-               ## test_prog__rpg__character__Character.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__character.concern
-                       ### test_prog__rpg__character__Character__age.definition
-                       ### test_prog__rpg__character__Character__age_61d.definition
-                       ### test_prog__rpg__character__Character__career.definition
-                       ### test_prog__rpg__character__Character__career_61d.definition
-                       ### test_prog__rpg__character__Character__health.definition
-                       ### test_prog__rpg__character__Character__health_61d.definition
-                       ### test_prog__rpg__character__Character__max_health.definition
-                       ### test_prog__rpg__character__Character__name.definition
-                       ### test_prog__rpg__character__Character__name_61d.definition
-                       ### test_prog__rpg__character__Character__quit.definition
-                       ### test_prog__rpg__character__Character__race.definition
-                       ### test_prog__rpg__character__Character__race_61d.definition
-                       ### test_prog__rpg__character__Character__sex.definition
-                       ### test_prog__rpg__character__Character__sex_61d.definition
-                       ### test_prog__rpg__character__Character__total_endurance.definition
-                       ### test_prog__rpg__character__Character__total_intelligence.definition
-                       ### test_prog__rpg__character__Character__total_strengh.definition
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Character__hit_points.definition
-                               #### test_prog__rpg__combat__Character__hit_points.lin
-
-MPropertyPage age
-       # age.section
-               ## test_prog__rpg__character__Character__age.intro
-
-MPropertyPage age=
-       # age=.section
-               ## test_prog__rpg__character__Character__age_61d.intro
-
-MPropertyPage career
-       # career.section
-               ## test_prog__rpg__character__Character__career.intro
-
-MPropertyPage career=
-       # career=.section
-               ## test_prog__rpg__character__Character__career_61d.intro
-
-MPropertyPage health
-       # health.section
-               ## test_prog__rpg__character__Character__health.intro
-
-MPropertyPage health=
-       # health=.section
-               ## test_prog__rpg__character__Character__health_61d.intro
-
-MPropertyPage max_health
-       # max_health.section
-               ## test_prog__rpg__character__Character__max_health.intro
-
-MPropertyPage name
-       # name.section
-               ## test_prog__rpg__character__Character__name.intro
-
-MPropertyPage name=
-       # name=.section
-               ## test_prog__rpg__character__Character__name_61d.intro
-
-MPropertyPage quit
-       # quit.section
-               ## test_prog__rpg__character__Character__quit.intro
-
-MPropertyPage race
-       # race.section
-               ## test_prog__rpg__character__Character__race.intro
-
-MPropertyPage race=
-       # race=.section
-               ## test_prog__rpg__character__Character__race_61d.intro
-
-MPropertyPage sex
-       # sex.section
-               ## test_prog__rpg__character__Character__sex.intro
-
-MPropertyPage sex=
-       # sex=.section
-               ## test_prog__rpg__character__Character__sex_61d.intro
-
-MPropertyPage total_endurance
-       # total_endurance.section
-               ## test_prog__rpg__character__Character__total_endurance.intro
-
-MPropertyPage total_intelligence
-       # total_intelligence.section
-               ## test_prog__rpg__character__Character__total_intelligence.intro
-
-MPropertyPage total_strengh
-       # total_strengh.section
-               ## test_prog__rpg__character__Character__total_strengh.intro
-
-MModulePage combat
-       # combat.section
-               ## test_prog__rpg__combat.intro
-               ## test_prog__rpg__combat.importation
-                       ### test_prog__rpg__combat.graph
-                       ### list.group
-                               #### test_prog__rpg__combat.imports
-                               #### test_prog__rpg__combat.clients
-               ## test_prog__rpg__combat.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Combatable.definition-list
-                               #### test_prog__rpg__combat__Combatable.definition
-                                       ##### test_prog__rpg__combat__Combatable.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__combat__Combatable.intros
-                                                       ####### test_prog__rpg__combat__Combatable.redefs
-                       ### test_prog__rpg__combat__Weapon.definition-list
-                               #### test_prog__rpg__combat__Weapon.definition
-                                       ##### test_prog__rpg__combat__Weapon.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__combat__Weapon.intros
-                                                       ####### test_prog__rpg__combat__Weapon.redefs
-               ## test_prog__rpg__races.concern
-                       ### test_prog__rpg__races__Dwarf.definition-list
-                               #### test_prog__rpg__races__Dwarf.definition
-                               #### test_prog__rpg__combat__Dwarf.definition
-                                       ##### test_prog__rpg__combat__Dwarf.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__combat__Dwarf.intros
-                                                       ####### test_prog__rpg__combat__Dwarf.redefs
-               ## test_prog__rpg__character.concern
-                       ### test_prog__rpg__character__Character.definition-list
-                               #### test_prog__rpg__character__Character.definition
-                               #### test_prog__rpg__combat__Character.definition
-                                       ##### test_prog__rpg__combat__Character.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__combat__Character.intros
-                                                       ####### test_prog__rpg__combat__Character.redefs
-
-MClassPage Combatable
-       # Combatable.section
-               ## test_prog__rpg__combat__Combatable.intro
-               ## test_prog__rpg__combat__Combatable.inheritance
-                       ### test_prog__rpg__combat__Combatable.graph
-                       ### list.group
-                               #### test_prog__rpg__combat__Combatable.parents
-                               #### test_prog__rpg__combat__Combatable.ancestors
-                               #### test_prog__rpg__combat__Combatable.children
-                               #### test_prog__rpg__combat__Combatable.descendants
-               ## test_prog__rpg__combat__Combatable.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__rpg__combat__Combatable.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Combatable__attack.definition
-                       ### test_prog__rpg__combat__Combatable__defend.definition
-                       ### test_prog__rpg__combat__Combatable__direct_attack.definition
-                       ### test_prog__rpg__combat__Combatable__hit_points.definition
-                       ### test_prog__rpg__combat__Combatable__is_dead.definition
-
-MPropertyPage attack
-       # attack.section
-               ## test_prog__rpg__combat__Combatable__attack.intro
-
-MPropertyPage defend
-       # defend.section
-               ## test_prog__rpg__combat__Combatable__defend.intro
-
-MPropertyPage direct_attack
-       # direct_attack.section
-               ## test_prog__rpg__combat__Combatable__direct_attack.intro
-
-MPropertyPage hit_points
-       # hit_points.section
-               ## test_prog__rpg__combat__Combatable__hit_points.intro
-               ## test_prog__rpg__combat__Combatable__hit_points.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Character__hit_points.definition
-
-MPropertyPage is_dead
-       # is_dead.section
-               ## test_prog__rpg__combat__Combatable__is_dead.intro
-
-MClassPage Weapon
-       # Weapon.section
-               ## test_prog__rpg__combat__Weapon.intro
-               ## test_prog__rpg__combat__Weapon.inheritance
-                       ### test_prog__rpg__combat__Weapon.graph
-                       ### list.group
-                               #### test_prog__rpg__combat__Weapon.parents
-                               #### test_prog__rpg__combat__Weapon.ancestors
-                               #### test_prog__rpg__combat__Weapon.children
-                               #### test_prog__rpg__combat__Weapon.descendants
-               ## test_prog__rpg__combat__Weapon.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__rpg__combat__Weapon.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Weapon__dps.definition
-
-MPropertyPage dps
-       # dps.section
-               ## test_prog__rpg__combat__Weapon__dps.intro
-               ## test_prog__rpg__combat__Weapon__dps.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Dwarf__dps.definition
-
-MModulePage races
-       # races.section
-               ## test_prog__rpg__races.intro
-               ## test_prog__rpg__races.importation
-                       ### test_prog__rpg__races.graph
-                       ### list.group
-                               #### test_prog__rpg__races.imports
-                               #### test_prog__rpg__races.clients
-               ## test_prog__rpg__races.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__races.concern
-                       ### test_prog__rpg__races__Dwarf.definition-list
-                               #### test_prog__rpg__races__Dwarf.definition
-                                       ##### test_prog__rpg__races__Dwarf.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__races__Dwarf.intros
-                                                       ####### test_prog__rpg__races__Dwarf.redefs
-                       ### test_prog__rpg__races__Elf.definition-list
-                               #### test_prog__rpg__races__Elf.definition
-                                       ##### test_prog__rpg__races__Elf.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__races__Elf.intros
-                                                       ####### test_prog__rpg__races__Elf.redefs
-                       ### test_prog__rpg__races__Human.definition-list
-                               #### test_prog__rpg__races__Human.definition
-                                       ##### test_prog__rpg__races__Human.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__races__Human.intros
-                                                       ####### test_prog__rpg__races__Human.redefs
-                       ### test_prog__rpg__races__Race.definition-list
-                               #### test_prog__rpg__races__Race.definition
-                                       ##### test_prog__rpg__races__Race.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__rpg__races__Race.intros
-                                                       ####### test_prog__rpg__races__Race.redefs
-
-MClassPage Dwarf
-       # Dwarf.section
-               ## test_prog__rpg__races__Dwarf.intro
-               ## test_prog__rpg__races__Dwarf.inheritance
-                       ### test_prog__rpg__races__Dwarf.graph
-                       ### list.group
-                               #### test_prog__rpg__races__Dwarf.parents
-                               #### test_prog__rpg__races__Dwarf.ancestors
-                               #### test_prog__rpg__races__Dwarf.children
-                               #### test_prog__rpg__races__Dwarf.descendants
-               ## test_prog__rpg__races__Dwarf.constructors
-                       ### test_prog__rpg__races__Dwarf__init.definition
-                               #### test_prog__rpg__races__Dwarf__init.lin
-               ## test_prog__rpg__races__Dwarf.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__races.concern
-               ## test_prog__rpg__combat.concern
-                       ### test_prog__rpg__combat__Dwarf__dps.definition
-                               #### test_prog__rpg__combat__Dwarf__dps.lin
-
-MClassPage Elf
-       # Elf.section
-               ## test_prog__rpg__races__Elf.intro
-               ## test_prog__rpg__races__Elf.inheritance
-                       ### test_prog__rpg__races__Elf.graph
-                       ### list.group
-                               #### test_prog__rpg__races__Elf.parents
-                               #### test_prog__rpg__races__Elf.ancestors
-                               #### test_prog__rpg__races__Elf.children
-                               #### test_prog__rpg__races__Elf.descendants
-               ## test_prog__rpg__races__Elf.constructors
-                       ### test_prog__rpg__races__Elf__init.definition
-                               #### test_prog__rpg__races__Elf__init.lin
-               ## test_prog__rpg__races__Elf.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__races.concern
-
-MClassPage Human
-       # Human.section
-               ## test_prog__rpg__races__Human.intro
-               ## test_prog__rpg__races__Human.inheritance
-                       ### test_prog__rpg__races__Human.graph
-                       ### list.group
-                               #### test_prog__rpg__races__Human.parents
-                               #### test_prog__rpg__races__Human.ancestors
-                               #### test_prog__rpg__races__Human.children
-                               #### test_prog__rpg__races__Human.descendants
-               ## test_prog__rpg__races__Human.constructors
-                       ### test_prog__rpg__races__Human__init.definition
-                               #### test_prog__rpg__races__Human__init.lin
-               ## test_prog__rpg__races__Human.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__races.concern
-
-MClassPage Race
-       # Race.section
-               ## test_prog__rpg__races__Race.intro
-               ## test_prog__rpg__races__Race.inheritance
-                       ### test_prog__rpg__races__Race.graph
-                       ### list.group
-                               #### test_prog__rpg__races__Race.parents
-                               #### test_prog__rpg__races__Race.ancestors
-                               #### test_prog__rpg__races__Race.children
-                               #### test_prog__rpg__races__Race.descendants
-               ## test_prog__rpg__races__Race.constructors
-                       ### test_prog__rpg__races__Race__init.definition
-                               #### test_prog__rpg__races__Race__init.lin
-               ## test_prog__rpg__races__Race.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__rpg.concern
-               ## test_prog__rpg__races.concern
-                       ### test_prog__rpg__races__Race__base_endurance.definition
-                       ### test_prog__rpg__races__Race__base_endurance_61d.definition
-                       ### test_prog__rpg__races__Race__base_intelligence.definition
-                       ### test_prog__rpg__races__Race__base_intelligence_61d.definition
-                       ### test_prog__rpg__races__Race__base_strength.definition
-                       ### test_prog__rpg__races__Race__base_strength_61d.definition
-
-MPropertyPage base_endurance
-       # base_endurance.section
-               ## test_prog__rpg__races__Race__base_endurance.intro
-
-MPropertyPage base_endurance=
-       # base_endurance=.section
-               ## test_prog__rpg__races__Race__base_endurance_61d.intro
-
-MPropertyPage base_intelligence
-       # base_intelligence.section
-               ## test_prog__rpg__races__Race__base_intelligence.intro
-
-MPropertyPage base_intelligence=
-       # base_intelligence=.section
-               ## test_prog__rpg__races__Race__base_intelligence_61d.intro
-
-MPropertyPage base_strength
-       # base_strength.section
-               ## test_prog__rpg__races__Race__base_strength.intro
-
-MPropertyPage base_strength=
-       # base_strength=.section
-               ## test_prog__rpg__races__Race__base_strength_61d.intro
-
-MModulePage rpg
-       # rpg.section
-               ## test_prog__rpg__rpg.intro
-               ## test_prog__rpg__rpg.importation
-                       ### test_prog__rpg__rpg.graph
-                       ### list.group
-                               #### test_prog__rpg__rpg.imports
-                               #### test_prog__rpg__rpg.clients
-
-MGroupPage tests
-       # tests.section
-               ## test_prog__tests.intro
-               ## test_prog__tests.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__tests.concern
-               ## test_prog__tests-.concern
-                       ### test_prog__tests-.definition
-                               #### test_prog__tests-.intros_redefs
-                                       ##### list.group
-                                               ###### test_prog__tests-.intros
-                                               ###### test_prog__tests-.redefs
-
-MModulePage test_game
-       # test_game.section
-               ## test_prog__tests-.intro
-               ## test_prog__tests-.importation
-                       ### test_prog__tests-.graph
-                       ### list.group
-                               #### test_prog__tests-.imports
-                               #### test_prog__tests-.clients
-               ## test_prog__tests-.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__tests.concern
-               ## test_prog__tests-.concern
-                       ### test_prog__tests-__GameTest.definition-list
-                               #### test_prog__tests-__GameTest.definition
-                                       ##### test_prog__tests-__GameTest.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__tests-__GameTest.intros
-                                                       ####### test_prog__tests-__GameTest.redefs
-                       ### test_prog__tests-__TestGame.definition-list
-                               #### test_prog__tests-__TestGame.definition
-                                       ##### test_prog__tests-__TestGame.intros_redefs
-                                               ###### list.group
-                                                       ####### test_prog__tests-__TestGame.intros
-                                                       ####### test_prog__tests-__TestGame.redefs
-
-MClassPage GameTest
-       # GameTest.section
-               ## test_prog__tests-__GameTest.intro
-               ## test_prog__tests-__GameTest.inheritance
-                       ### test_prog__tests-__GameTest.graph
-                       ### list.group
-                               #### test_prog__tests-__GameTest.parents
-                               #### test_prog__tests-__GameTest.ancestors
-                               #### test_prog__tests-__GameTest.children
-                               #### test_prog__tests-__GameTest.descendants
-               ## test_prog__tests-__GameTest.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__tests-__GameTest.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__tests.concern
-               ## test_prog__tests-.concern
-                       ### test_prog__tests-__GameTest__test_game.definition
-
-MPropertyPage test_game
-       # test_game.section
-               ## test_prog__tests-__GameTest__test_game.intro
-
-MClassPage TestGame
-       # TestGame.section
-               ## test_prog__tests-__TestGame.intro
-               ## test_prog__tests-__TestGame.inheritance
-                       ### test_prog__tests-__TestGame.graph
-                       ### list.group
-                               #### test_prog__tests-__TestGame.parents
-                               #### test_prog__tests-__TestGame.ancestors
-                               #### test_prog__tests-__TestGame.children
-                               #### test_prog__tests-__TestGame.descendants
-               ## test_prog__tests-__TestGame.constructors
-                       ### test_prog__platform-__Object__init.definition
-               ## test_prog__tests-__TestGame.concerns
-               ## test_prog.concern
-               ## test_prog.concern
-               ## test_prog__tests.concern
-               ## test_prog__tests-.concern
-                       ### test_prog__tests-__TestGame__player_characters.definition
-                               #### test_prog__tests-__TestGame__player_characters.lin
-                       ### test_prog__tests-__TestGame__player_characters_61d.definition
-
-MPropertyPage player_characters=
-       # player_characters=.section
-               ## test_prog__tests-__TestGame__player_characters_61d.intro
-
-Generated 114 pages
- list:
-  MPropertyPage: 62 (54.38%)
-  MClassPage: 23 (20.17%)
-  MModulePage: 11 (9.64%)
-  ReadmePage: 8 (7.01%)
-  MGroupPage: 8 (7.01%)
-  SearchPage: 1 (0.87%)
-  OverviewPage: 1 (0.87%)
-Found 212 mentities
- list:
-  MMethodDef: 79 (37.26%)
-  MMethod: 61 (28.77%)
-  MClassDef: 26 (12.26%)
-  MClass: 23 (10.84%)
-  MModule: 11 (5.18%)
-  MGroup: 8 (3.77%)
-  MPackage: 2 (0.94%)
-  MVirtualTypeDef: 1 (0.47%)
-  MVirtualTypeProp: 1 (0.47%)
-quicksearch-list.js
+Parsing code...
+Generating documentation pages...
+Generated 111/111 pages
+ PageHome: 1
+ PageMPackage: 2
+ PageMGroup: 7
+ PageMModule: 10
+ PageMClass: 22
+ PageMProperty: 61
+ PagePerson: 6
+ PageTag: 2
index cf89e02..e7f3ab8 100644 (file)
 </span></span><span class="line" id="L27"><span class="nc_k">end</span>
 </span></span><span class="line" id="L28">
 </span><span class="nc_cdef foldable" id="base_simple3$A"><span class="line" id="L29"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class A" data-title="&lt;a href=&#34;#base_simple3$A&#34;&gt;class A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;A&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
-</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L32"><span class="nc_k">end</span>
 </span></span><span class="line" id="L33">
 </span><span class="nc_cdef foldable" id="base_simple3$B"><span class="line" id="L34"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;class B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;B&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span>
-</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
+</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
 </span><span class="line" id="L37">    <span class="nc_k">do</span>
-</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
+</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
 </span><span class="line" id="L40">    <span class="nc_k">end</span>
 </span></span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i popupable" title="call base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;call base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L42"><span class="nc_k">end</span>
 </span></span><span class="line" id="L43">
 </span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="L44"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class C" data-title="&lt;a href=&#34;#base_simple3$C&#34;&gt;class C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;C&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span>
-</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
+</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
 </span></span><span class="line" id="L47"><span class="nc_k">end</span>
 </span></span><span class="line" id="L48">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
 </span></span><span class="line" id="L52">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L54"><span class="nc_i popupable" title="call base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;call base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">foo</span>
-</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
+</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
 </span><span class="line" id="L56"><span class="nc_i popupable" title="call base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;call base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">baz</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L57">
-</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3$A$init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
+</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3$A$init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3$A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
 </span><span class="line" id="L59"><span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span><span class="popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L60">
-</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3$B$init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
+</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3$B$init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
 </span><span class="line" id="L62"><span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span><span class="popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L63">
-</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3$C$init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
+</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3$C$init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3$C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
 </span><span class="line" id="L65"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L66"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span></span>
\ No newline at end of file
index 9a585f7..204c980 100644 (file)
 </span></span><span class="line" id="L27"><span class="nc_k">end</span>
 </span></span><span class="line" id="L28">
 </span><span class="nc_cdef foldable" id="base_simple3$A"><span class="line" id="L29"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class A" data-title="&lt;a href=&#34;#base_simple3$A&#34;&gt;class A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;A&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
-</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L32"><span class="nc_k">end</span>
 </span></span><span class="line" id="L33">
 </span><span class="nc_cdef foldable" id="base_simple3$B"><span class="line" id="L34"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;class B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;B&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span>
-</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
+</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
 </span><span class="line" id="L37">    <span class="nc_k">do</span>
-</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
+</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
 </span><span class="line" id="L40">    <span class="nc_k">end</span>
 </span></span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i popupable" title="call base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;call base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L42"><span class="nc_k">end</span>
 </span></span><span class="line" id="L43">
 </span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="L44"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class C" data-title="&lt;a href=&#34;#base_simple3$C&#34;&gt;class C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;C&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span>
-</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
+</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
 </span></span><span class="line" id="L47"><span class="nc_k">end</span>
 </span></span><span class="line" id="L48">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
 </span></span><span class="line" id="L52">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L54"><span class="nc_i popupable" title="call base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;call base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">foo</span>
-</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
+</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
 </span><span class="line" id="L56"><span class="nc_i popupable" title="call base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;call base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Sys$baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">baz</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L57">
-</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3$A$init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
+</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3$A$init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3$A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
 </span><span class="line" id="L59"><span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3$A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span><span class="popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3$A$run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$A$run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L60">
-</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3$B$init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
+</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3$B$init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
 </span><span class="line" id="L62"><span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span><span class="popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L63">
-</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3$C$init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
+</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3$C$init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Object$init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3$C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
 </span><span class="line" id="L65"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L66"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3$C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span></span></pre><script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
index 1c71ab2..f1c2d87 100644 (file)
@@ -1,10 +1,10 @@
-<span class="nitcode"><span class="line" id="XYZ38">           <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span><span class="line" id="XYZ39">          <span class="nc_k popupable" title="B" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
+<span class="nitcode"><span class="line" id="XYZ38">           <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="line" id="XYZ39">          <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3$B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val=&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
 </span><span class="line" id="XYZ40">  <span class="nc_k">end</span>
 </span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="XYZ41">   <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3$B$run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i popupable" title="call base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3$B$val&#34;&gt;call base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$B$val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int$output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="XYZ42"><span class="nc_k">end</span>
 </span><span class="line" id="XYZ43">
 </span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="XYZ44"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class C" data-title="&lt;a href=&#34;#base_simple3$C&#34;&gt;class C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;C&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3$Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span>
-</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="XYZ45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="XYZ46"> <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
+</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="XYZ45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3$C$val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="XYZ46"> <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3$C$val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3$Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3$Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
 </span></span></span></span>
\ No newline at end of file
index aa14ea5..90f6ed3 100644 (file)
 </span></span><span class="line" id="L16">
 </span><span class="line" id="L17"><span class="nc_k">import</span> <span class="nc_k">end</span>
 </span><span class="line" id="L18">
-</span><span class="nc_cdef foldable" id="base_simple3$Object"><span class="line" id="L19"><span class="nc_k">interface</span> <span class="nc_t nc_def titled" title="class Object">Object</span>
+</span><span class="nc_cdef foldable" id="base_simple3$Object"><span class="line" id="L19"><span class="nc_k">interface</span> <a class="titled" href="#base_simple3$Object" title="class Object"><span class="nc_t nc_def">Object</span></a>
 </span><span class="line" id="L20"><span class="nc_k">end</span>
 </span></span><span class="line" id="L21">
-</span><span class="nc_cdef foldable" id="base_simple3$Bool"><span class="line" id="L22"><span class="nc_k">enum</span> <span class="nc_t nc_def titled" title="class Bool">Bool</span>
+</span><span class="nc_cdef foldable" id="base_simple3$Bool"><span class="line" id="L22"><span class="nc_k">enum</span> <a class="titled" href="#base_simple3$Bool" title="class Bool"><span class="nc_t nc_def">Bool</span></a>
 </span><span class="line" id="L23"><span class="nc_k">end</span>
 </span></span><span class="line" id="L24">
-</span><span class="nc_cdef foldable" id="base_simple3$Int"><span class="line" id="L25"><span class="nc_k">enum</span> <span class="nc_t nc_def titled" title="class Int">Int</span>
-</span><span class="nc_pdef foldable" id="base_simple3$Int$output"><span class="line" id="L26">        <span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$Int$output"><span class="nc_i">output</span></span> <span class="nc_k">is</span> <span class="nc_i">intern</span>
+</span><span class="nc_cdef foldable" id="base_simple3$Int"><span class="line" id="L25"><span class="nc_k">enum</span> <a class="titled" href="#base_simple3$Int" title="class Int"><span class="nc_t nc_def">Int</span></a>
+</span><span class="nc_pdef foldable" id="base_simple3$Int$output"><span class="line" id="L26">        <span class="nc_k">fun</span> <a class="titled" href="#base_simple3$Int$output" title="base_simple3$Int$output"><span class="nc_def"></span><span class="nc_i">output</span></a> <span class="nc_k">is</span> <span class="nc_i">intern</span>
 </span></span><span class="line" id="L27"><span class="nc_k">end</span>
 </span></span><span class="line" id="L28">
-</span><span class="nc_cdef foldable" id="base_simple3$A"><span class="line" id="L29"><span class="nc_k">class</span> <span class="nc_t nc_def titled" title="class A">A</span>
-</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l titled" title="Int">5</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$A$run"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l titled" title="Int">6</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
+</span><span class="nc_cdef foldable" id="base_simple3$A"><span class="line" id="L29"><span class="nc_k">class</span> <a class="titled" href="#base_simple3$A" title="class A"><span class="nc_t nc_def">A</span></a>
+</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">5</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <a class="titled" href="#base_simple3$A$run" title="base_simple3$A$run"><span class="nc_def"></span><span class="nc_i">run</span></a> <span class="nc_k">do</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">6</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
 </span></span><span class="line" id="L32"><span class="nc_k">end</span>
 </span></span><span class="line" id="L33">
-</span><span class="nc_cdef foldable" id="base_simple3$B"><span class="line" id="L34"><span class="nc_k">class</span> <span class="nc_t nc_def titled" title="class B">B</span>
-</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def titled" title="base_simple3$B$val">val</span><span>:</span> <span class="nc_t titled" title="Int">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v titled" title="v: Int">v</span><span>:</span> <span class="nc_t titled" title="Int">Int</span><span>)</span>
+</span><span class="nc_cdef foldable" id="base_simple3$B"><span class="line" id="L34"><span class="nc_k">class</span> <a class="titled" href="#base_simple3$B" title="class B"><span class="nc_t nc_def">B</span></a>
+</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <a class="titled" href="#base_simple3$B$val" title="base_simple3$B$val"><span class="nc_i nc_def">val</span></a><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a>
+</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v titled" title="v: Int">v</span><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a><span>)</span>
 </span><span class="line" id="L37">    <span class="nc_k">do</span>
-</span><span class="line" id="L38">            <span class="nc_l titled" title="Int">7</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span><span class="line" id="L39">            <span class="nc_k titled" title="B">self</span><span class="titled" title="call base_simple3$B$val=">.</span><span class="nc_i titled" title="call base_simple3$B$val=">val</span> <span class="titled" title="call base_simple3$B$val=">=</span> <span class="nc_i nc_v titled" title="v: Int">v</span>
+</span><span class="line" id="L38">            <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">7</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span><span class="line" id="L39">            <a class="titled" href="#base_simple3$B" title="B"><span class="nc_k">self</span></a><a class="titled" href="#base_simple3$B$val=" title="call base_simple3$B$val="><span>.</span></a><a class="titled" href="#base_simple3$B$val=" title="call base_simple3$B$val="><span class="nc_i">val</span></a> <a class="titled" href="#base_simple3$B$val=" title="call base_simple3$B$val="><span>=</span></a> <span class="nc_i nc_v titled" title="v: Int">v</span>
 </span><span class="line" id="L40">    <span class="nc_k">end</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">      <span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$B$run"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i titled" title="call base_simple3$B$val">val</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">      <span class="nc_k">fun</span> <a class="titled" href="#base_simple3$B$run" title="base_simple3$B$run"><span class="nc_def"></span><span class="nc_i">run</span></a> <span class="nc_k">do</span> <a class="titled" href="#base_simple3$B$val" title="call base_simple3$B$val"><span class="nc_i">val</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
 </span></span><span class="line" id="L42"><span class="nc_k">end</span>
 </span></span><span class="line" id="L43">
-</span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="L44"><span class="nc_k">class</span> <span class="nc_t nc_def titled" title="class C">C</span>
-</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def titled" title="base_simple3$C$val1">val1</span><span>:</span> <span class="nc_t titled" title="Int">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def titled" title="base_simple3$C$val2">val2</span><span>:</span> <span class="nc_t titled" title="Int">Int</span> <span>=</span> <span class="nc_l titled" title="Int">10</span>
+</span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="L44"><span class="nc_k">class</span> <a class="titled" href="#base_simple3$C" title="class C"><span class="nc_t nc_def">C</span></a>
+</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <a class="titled" href="#base_simple3$C$val1" title="base_simple3$C$val1"><span class="nc_i nc_def">val1</span></a><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a>
+</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <a class="titled" href="#base_simple3$C$val2" title="base_simple3$C$val2"><span class="nc_i nc_def">val2</span></a><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a> <span>=</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">10</span></a>
 </span></span><span class="line" id="L47"><span class="nc_k">end</span>
 </span></span><span class="line" id="L48">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$Sys$foo"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l titled" title="Int">2</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$Sys$bar"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v titled" title="i: Int">i</span><span>:</span> <span class="nc_t titled" title="Int">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v titled" title="i: Int">i</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def titled" title="base_simple3$Sys$baz"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t titled" title="Int">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l titled" title="Int">4</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <a class="titled" href="#base_simple3$Sys$foo" title="base_simple3$Sys$foo"><span class="nc_def"></span><span class="nc_i">foo</span></a> <span class="nc_k">do</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">2</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <a class="titled" href="#base_simple3$Sys$bar" title="base_simple3$Sys$bar"><span class="nc_def"></span><span class="nc_i">bar</span></a><span>(</span><span class="nc_i nc_v titled" title="i: Int">i</span><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v titled" title="i: Int">i</span><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <a class="titled" href="#base_simple3$Sys$baz" title="base_simple3$Sys$baz"><span class="nc_def"></span><span class="nc_i">baz</span></a><span>:</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_t">Int</span></a> <span class="nc_k">do</span> <span class="nc_k">return</span> <a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">4</span></a>
 </span></span><span class="line" id="L52">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l titled" title="Int">1</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span><span class="line" id="L54"><span class="nc_i titled" title="call base_simple3$Sys$foo">foo</span>
-</span><span class="line" id="L55"><span class="nc_i titled" title="call base_simple3$Sys$bar">bar</span><span>(</span><span class="nc_l titled" title="Int">3</span><span>)</span>
-</span><span class="line" id="L56"><span class="nc_i titled" title="call base_simple3$Sys$baz">baz</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">1</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span><span class="line" id="L54"><a class="titled" href="#base_simple3$Sys$foo" title="call base_simple3$Sys$foo"><span class="nc_i">foo</span></a>
+</span><span class="line" id="L55"><a class="titled" href="#base_simple3$Sys$bar" title="call base_simple3$Sys$bar"><span class="nc_i">bar</span></a><span>(</span><a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">3</span></a><span>)</span>
+</span><span class="line" id="L56"><a class="titled" href="#base_simple3$Sys$baz" title="call base_simple3$Sys$baz"><span class="nc_i">baz</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
 </span><span class="line" id="L57">
-</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="a: A">a</span> <span>=</span> <span class="nc_k titled" title="call base_simple3$A$init">new</span> <span class="nc_t titled" title="A">A</span>
-</span><span class="line" id="L59"><span class="nc_i nc_v titled" title="a: A">a</span><span class="titled" title="call base_simple3$A$run">.</span><span class="nc_i titled" title="call base_simple3$A$run">run</span>
+</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="a: A">a</span> <span>=</span> <a class="titled" href="#base_simple3$A$init" title="call base_simple3$A$init"><span class="nc_k">new</span></a> <a class="titled" href="#base_simple3$A" title="A"><span class="nc_t">A</span></a>
+</span><span class="line" id="L59"><span class="nc_i nc_v titled" title="a: A">a</span><a class="titled" href="#base_simple3$A$run" title="call base_simple3$A$run"><span>.</span></a><a class="titled" href="#base_simple3$A$run" title="call base_simple3$A$run"><span class="nc_i">run</span></a>
 </span><span class="line" id="L60">
-</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="b: B">b</span> <span>=</span> <span class="nc_k titled" title="call base_simple3$B$init">new</span> <span class="nc_t titled" title="B">B</span><span>(</span><span class="nc_l titled" title="Int">8</span><span>)</span>
-</span><span class="line" id="L62"><span class="nc_i nc_v titled" title="b: B">b</span><span class="titled" title="call base_simple3$B$run">.</span><span class="nc_i titled" title="call base_simple3$B$run">run</span>
+</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="b: B">b</span> <span>=</span> <a class="titled" href="#base_simple3$B$init" title="call base_simple3$B$init"><span class="nc_k">new</span></a> <a class="titled" href="#base_simple3$B" title="B"><span class="nc_t">B</span></a><span>(</span><a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">8</span></a><span>)</span>
+</span><span class="line" id="L62"><span class="nc_i nc_v titled" title="b: B">b</span><a class="titled" href="#base_simple3$B$run" title="call base_simple3$B$run"><span>.</span></a><a class="titled" href="#base_simple3$B$run" title="call base_simple3$B$run"><span class="nc_i">run</span></a>
 </span><span class="line" id="L63">
-</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="c: C">c</span> <span>=</span> <span class="nc_k titled" title="call base_simple3$C$init">new</span> <span class="nc_t titled" title="C">C</span><span>(</span><span class="nc_l titled" title="Int">9</span><span>)</span>
-</span><span class="line" id="L65"><span class="nc_i nc_v titled" title="c: C">c</span><span class="titled" title="call base_simple3$C$val1">.</span><span class="nc_i titled" title="call base_simple3$C$val1">val1</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
-</span><span class="line" id="L66"><span class="nc_i nc_v titled" title="c: C">c</span><span class="titled" title="call base_simple3$C$val2">.</span><span class="nc_i titled" title="call base_simple3$C$val2">val2</span><span class="titled" title="call base_simple3$Int$output">.</span><span class="nc_i titled" title="call base_simple3$Int$output">output</span>
+</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v titled" title="c: C">c</span> <span>=</span> <a class="titled" href="#base_simple3$C$init" title="call base_simple3$C$init"><span class="nc_k">new</span></a> <a class="titled" href="#base_simple3$C" title="C"><span class="nc_t">C</span></a><span>(</span><a class="titled" href="#base_simple3$Int" title="Int"><span class="nc_l">9</span></a><span>)</span>
+</span><span class="line" id="L65"><span class="nc_i nc_v titled" title="c: C">c</span><a class="titled" href="#base_simple3$C$val1" title="call base_simple3$C$val1"><span>.</span></a><a class="titled" href="#base_simple3$C$val1" title="call base_simple3$C$val1"><span class="nc_i">val1</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
+</span><span class="line" id="L66"><span class="nc_i nc_v titled" title="c: C">c</span><a class="titled" href="#base_simple3$C$val2" title="call base_simple3$C$val2"><span>.</span></a><a class="titled" href="#base_simple3$C$val2" title="call base_simple3$C$val2"><span class="nc_i">val2</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span>.</span></a><a class="titled" href="#base_simple3$Int$output" title="call base_simple3$Int$output"><span class="nc_i">output</span></a>
 </span></span></span></pre><script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
 <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
 <script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script></body></html>
\ No newline at end of file
index 05313a1..139d036 100644 (file)
@@ -240,6 +240,22 @@ Average size of table by runtime class: 3.83
 Values never redefined: 17 (73.91%)
 generating package_hierarchy.dot
 generating module_hierarchy.dot
+--- Metrics of the explitic static types ---
+Total number of explicit static types: 9
+Statistics of type usage:
+ population: 4
+ minimum value: 1
+ maximum value: 6
+ total value: 9
+ average value: 2.25
+ distribution:
+  <=1: sub-population=3 (75.00%); cumulated value=3 (33.33%)
+  <=8: sub-population=1 (25.00%); cumulated value=6 (66.66%)
+ list:
+  Int: 6 (66.66%)
+  C: 1 (11.11%)
+  B: 1 (11.11%)
+  A: 1 (11.11%)
 
 # MClasses metrics
 
@@ -720,22 +736,6 @@ Warning: no source file for `base_simple3`
          min: base_simple3 (0.143)
          std: 0.0
          sum: 0.143
---- Metrics of the explitic static types ---
-Total number of explicit static types: 9
-Statistics of type usage:
- population: 4
- minimum value: 1
- maximum value: 6
- total value: 9
- average value: 2.25
- distribution:
-  <=1: sub-population=3 (75.00%); cumulated value=3 (33.33%)
-  <=8: sub-population=1 (25.00%); cumulated value=6 (66.66%)
- list:
-  Int: 6 (66.66%)
-  C: 1 (11.11%)
-  B: 1 (11.11%)
-  A: 1 (11.11%)
 
 # Mendel metrics
        large mclasses (threshold: 3.915)
index d98d744..a5a027f 100644 (file)
@@ -51,19 +51,19 @@ Float [
 Numeric -> Float [dir=back arrowtail=open style=dashed];
 
 Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l+ is_whitespace(): Bool\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Byte [dir=back arrowtail=open style=dashed];
 Numeric -> Byte [dir=back arrowtail=open style=dashed];
 
 Int [
- label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
+ label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Int [dir=back arrowtail=open style=dashed];
 Numeric -> Int [dir=back arrowtail=open style=dashed];
 
 Char [
- label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
+ label = "{Char||+ +(i: Int): Char\l+ -(i: Int): Char\l+ to_i(): Int\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Char [dir=back arrowtail=open style=dashed];
 
index 10ba4a8..f03123a 100644 (file)
@@ -51,19 +51,19 @@ Float [
 Numeric -> Float [dir=back arrowtail=open style=dashed];
 
 Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l+ is_whitespace(): Bool\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Byte [dir=back arrowtail=open style=dashed];
 Numeric -> Byte [dir=back arrowtail=open style=dashed];
 
 Int [
- label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
+ label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Int [dir=back arrowtail=open style=dashed];
 Numeric -> Int [dir=back arrowtail=open style=dashed];
 
 Char [
- label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
+ label = "{Char||+ +(i: Int): Char\l+ -(i: Int): Char\l+ to_i(): Int\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
 ]
 Discrete -> Char [dir=back arrowtail=open style=dashed];
 
index 3daede1..f1851ee 100644 (file)
@@ -1,17 +1,17 @@
 ==== Docunits of module test_nitunit::test_nitunit | tests: 5
 [OK] test_nitunit::test_nitunit
 [KO] test_nitunit$X
-     test_nitunit.nit:21,7--22,0: Runtime error in nitunit.out/test_nitunit-2.nit
+     test_nitunit.nit:23,7--24,0: Runtime error in nitunit.out/test_nitunit-2.nit with argument 0
      Output
        Runtime error: Assert failed (nitunit.out/test_nitunit-2.nit:5)
 
 [KO] test_nitunit$X$foo
-     test_nitunit.nit:24,8--25,0: Compilation error in nitunit.out/test_nitunit-3.nit
+     test_nitunit.nit:27,8--28,0: Compilation error in nitunit.out/test_nitunit-3.nit
      Output
        nitunit.out/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
 
 [KO] test_nitunit$X$foo1
-     test_nitunit.nit:28,15: Syntax Error: unexpected operator '!'.
+     test_nitunit.nit:32,15: Syntax Error: unexpected operator '!'.
 [OK] test_nitunit$X$foo2
 
 ==== Test-suite of module test_test_nitunit::test_test_nitunit | tests: 3
@@ -28,7 +28,7 @@ Test suites: Classes: 1; Test Cases: 3; Failures: 1
 [FAILURE] 4/8 tests failed.
 `nitunit.out` is not removed for investigation.
 <testsuites><testsuite package="test_nitunit::test_nitunit"><testcase classname="nitunit.test_nitunit::test_nitunit.&lt;module&gt;" name="&lt;module&gt;" time="0.0"><system-err></system-err><system-out>assert true
-</system-out></testcase><testcase classname="nitunit.test_nitunit.X" name="&lt;class&gt;" time="0.0"><error message="Runtime error in nitunit.out&#47;test_nitunit-2.nit">Runtime error: Assert failed (nitunit.out&#47;test_nitunit-2.nit:5)
+</system-out></testcase><testcase classname="nitunit.test_nitunit.X" name="&lt;class&gt;" time="0.0"><error message="Runtime error in nitunit.out&#47;test_nitunit-2.nit with argument 0">Runtime error: Assert failed (nitunit.out&#47;test_nitunit-2.nit:5)
 </error><system-out>assert false
 </system-out></testcase><testcase classname="nitunit.test_nitunit.X" name="foo" time="0.0"><failure message="Compilation error in nitunit.out&#47;test_nitunit-3.nit">nitunit.out&#47;test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
 </failure><system-out>assert undefined_identifier
index 30f2862..afcfb13 100644 (file)
@@ -5,7 +5,7 @@
        Runtime error: Assert failed (nitunit.out/test_nitunit3-0.nit:7)
 
 [KO] test_nitunit3>#2
-     test_nitunit3/README.md:7,3--5: Syntax Error: unexpected malformed character '\].
+     test_nitunit3/README.md:8,3--5: Syntax Error: unexpected malformed character '\].
 
 ==== Docunits of module test_nitunit3::test_nitunit3 | tests: 1
 [OK] test_nitunit3::test_nitunit3
index 12d09fe..4d7cf99 100644 (file)
@@ -1 +1 @@
-libevent warning: Opening localhost:80 failed
+libevent warning: Opening localhost:80 failed, Permission denied
index 2afbdc5..c3897e7 100644 (file)
@@ -22,7 +22,7 @@ s8 isa ASCIIFlatString
 String66515A
 s9 isa Regex
 /
-0x47String/
+71String/
 true
 false
 true
index 04f734e..bbe18c9 100644 (file)
@@ -1,10 +1,10 @@
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
-caught 100000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
+caught 10000 aborts
index 2fa91ac..c9cc4e2 100644 (file)
 <h1 id="base_simple3___base_simple3__Int___output">base_simple3$Int$output</h1>
 <pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Int$output"><span class="line" id="L26">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;output&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">output</span></span> <span class="nc_k">is</span> <span class="nc_i">intern</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__A___Object__init">base_simple3$A$Object::init</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">  <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">  <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__A___run">base_simple3$A$run</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">   <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">   <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__B____val">base_simple3$B$_val</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__B___val">base_simple3$B$val</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__B___val_61d">base_simple3$B$val=</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__B___init">base_simple3$B$init</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">  <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">  <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
 </span><span class="line" id="L37">    <span class="nc_k">do</span>
-</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
+</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
 </span><span class="line" id="L40">    <span class="nc_k">end</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__B___run">base_simple3$B$run</h1>
 <pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">   <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i popupable" title="call base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;call base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C____val1">base_simple3$C$_val1</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C___val1">base_simple3$C$val1</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C___val1_61d">base_simple3$C$val1=</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C____val2">base_simple3$C$_val2</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C___val2">base_simple3$C$val2</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__C___val2_61d">base_simple3$C$val2=</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">        <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__Sys___foo">base_simple3$Sys$foo</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__Sys___bar">base_simple3$Sys$bar</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__Sys___baz">base_simple3$Sys$baz</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span></span></span></span></code></pre>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span></span></span></span></code></pre>
 <h1 id="base_simple3___base_simple3__Sys___main">base_simple3$Sys$main</h1>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L54"><span class="nc_i popupable" title="call base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;call base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">foo</span>
-</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
+</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
 </span><span class="line" id="L56"><span class="nc_i popupable" title="call base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;call base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">baz</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L57">
-</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3__A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
+</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
 </span><span class="line" id="L59"><span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span><span class="popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L60">
-</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
+</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
 </span><span class="line" id="L62"><span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span><span class="popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L63">
-</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3__C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
+</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
 </span><span class="line" id="L65"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L66"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h2>AST node: AModule at base_simple3.nit:17,1--66,13</h2>
 </span></span><span class="line" id="L27"><span class="nc_k">end</span>
 </span></span><span class="line" id="L28">
 </span><span class="nc_cdef foldable" id="base_simple3$A"><span class="line" id="L29"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class A" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;class A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;A&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
-</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">    <span class="nc_k">init</span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">5</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$A$run"><span class="line" id="L31">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">6</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L32"><span class="nc_k">end</span>
 </span></span><span class="line" id="L33">
 </span><span class="nc_cdef foldable" id="base_simple3$B"><span class="line" id="L34"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class B" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;class B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;B&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span>
-</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
+</span><span class="nc_pdef foldable" id="base_simple3$B$_val"><a id="base_simple3$B$val"></a><a id="base_simple3$B$val="></a><span class="line" id="L35">     <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$B$init"><span class="line" id="L36">     <span class="nc_k popupable" style="border-bottom: solid 2px red" title="Messages" data-content="&lt;div&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;1 message(s)&lt;&#47;b&gt; &lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;Warning: init with signature in base_simple3$B&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">init</span><span>(</span><span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span>
 </span><span class="line" id="L37">    <span class="nc_k">do</span>
-</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
+</span><span class="line" id="L38">            <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">7</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="line" id="L39">            <span class="nc_k popupable" title="B" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">self</span><span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span> <span class="popupable" title="call base_simple3$B$val=" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;call base_simple3$B$val=&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val_61d&#34;&gt;base_simple3$B$val=&lt;&#47;a&gt;&lt;span&gt;(val: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">=</span> <span class="nc_i nc_v popupable" title="v: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;v:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">v</span>
 </span><span class="line" id="L40">    <span class="nc_k">end</span>
 </span></span><span class="nc_pdef foldable" id="base_simple3$B$run"><span class="line" id="L41">      <span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;run&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">run</span></span> <span class="nc_k">do</span> <span class="nc_i popupable" title="call base_simple3$B$val" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;call base_simple3$B$val&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___val&#34;&gt;base_simple3$B$val&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span></span><span class="line" id="L42"><span class="nc_k">end</span>
 </span></span><span class="line" id="L43">
 </span><span class="nc_cdef foldable" id="base_simple3$C"><span class="line" id="L44"><span class="nc_k">class</span> <span class="nc_t nc_def popupable" title="class C" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;class C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;C&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;div class=&#34;dropdown&#34;&gt; &lt;a data-toggle=&#34;dropdown&#34; href=&#34;#&#34;&gt;&lt;b&gt;hier&lt;&#47;b&gt; super-classes&lt;span class=&#34;caret&#34;&gt;&lt;&#47;span&gt;&lt;&#47;a&gt;&lt;ul class=&#34;dropdown-menu&#34; role=&#34;menu&#34; aria-labelledby=&#34;dLabel&#34;&gt;&lt;li&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object&#34;&gt;base_simple3$Object&lt;&#47;a&gt;&lt;&#47;li&gt;&lt;&#47;ul&gt;&lt;&#47;div&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span>
-</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
+</span><span class="nc_pdef foldable" id="base_simple3$C$_val1"><a id="base_simple3$C$val1"></a><a id="base_simple3$C$val1="></a><span class="line" id="L45">  <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val1&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$C$_val2"><a id="base_simple3$C$val2"></a><a id="base_simple3$C$val2="></a><span class="line" id="L46">   <span class="nc_k">var</span> <span class="nc_i nc_def popupable" title="base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;val2&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span>=</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">10</span>
 </span></span><span class="line" id="L47"><span class="nc_k">end</span>
 </span></span><span class="line" id="L48">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
-</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$foo"><span class="line" id="L49"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;foo&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">foo</span></span> <span class="nc_k">do</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$bar"><span class="line" id="L50"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;bar&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">bar</span></span><span>(</span><span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span><span>)</span> <span class="nc_k">do</span> <span class="nc_i nc_v popupable" title="i: Int" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;i:&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">i</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span></span><span class="nc_pdef foldable" id="base_simple3$Sys$baz"><span class="line" id="L51"><span class="nc_k">fun</span> <span class="nc_def popupable" title="base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;fun&lt;&#47;b&gt; &lt;span&gt;baz&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover"><span class="nc_i">baz</span></span><span>:</span> <span class="nc_t popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">Int</span> <span class="nc_k">do</span> <span class="nc_k">return</span> <span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">4</span>
 </span></span><span class="line" id="L52">
-</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
+</span><span class="nc_pdef foldable" id="base_simple3$Sys$main"><span class="line" id="L53"><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L54"><span class="nc_i popupable" title="call base_simple3$Sys$foo" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;call base_simple3$Sys$foo&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___foo&#34;&gt;base_simple3$Sys$foo&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">foo</span>
-</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
+</span><span class="line" id="L55"><span class="nc_i popupable" title="call base_simple3$Sys$bar" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;call base_simple3$Sys$bar&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___bar&#34;&gt;base_simple3$Sys$bar&lt;&#47;a&gt;&lt;span&gt;(i: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">bar</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">3</span><span>)</span>
 </span><span class="line" id="L56"><span class="nc_i popupable" title="call base_simple3$Sys$baz" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;call base_simple3$Sys$baz&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Sys___baz&#34;&gt;base_simple3$Sys$baz&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">baz</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L57">
-</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3__A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
+</span><span class="line" id="L58"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$A$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;call base_simple3$A$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___Object__init&#34;&gt;base_simple3$A$init&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="A" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;A&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">A</span>
 </span><span class="line" id="L59"><span class="nc_i nc_v popupable" title="a: A" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;a:&lt;a href=&#34;#base_simple3___base_simple3__A&#34;&gt;base_simple3$A&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">a</span><span class="popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$A$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;call base_simple3$A$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__A___run&#34;&gt;base_simple3$A$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L60">
-</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
+</span><span class="line" id="L61"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$B$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;call base_simple3$B$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___init&#34;&gt;base_simple3$B$init&lt;&#47;a&gt;&lt;span&gt;(v: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="B" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;B&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">B</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">8</span><span>)</span>
 </span><span class="line" id="L62"><span class="nc_i nc_v popupable" title="b: B" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;b:&lt;a href=&#34;#base_simple3___base_simple3__B&#34;&gt;base_simple3$B&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">b</span><span class="popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$B$run" data-title="&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;call base_simple3$B$run&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__B___run&#34;&gt;base_simple3$B$run&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">run</span>
 </span><span class="line" id="L63">
-</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3__C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
+</span><span class="line" id="L64"><span class="nc_k">var</span> <span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span> <span>=</span> <span class="nc_k popupable" title="call base_simple3$C$init" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;call base_simple3$C$init&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___Object__init&#34;&gt;base_simple3$C$init&lt;&#47;a&gt;&lt;span&gt;(val1: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;)&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;b&gt;intro&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Object___init&#34;&gt;in base_simple3$Object&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">new</span> <span class="nc_t popupable" title="C" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;C&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">C</span><span>(</span><span class="nc_l popupable" title="Int" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;Int&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">9</span><span>)</span>
 </span><span class="line" id="L65"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val1" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;call base_simple3$C$val1&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val1&#34;&gt;base_simple3$C$val1&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val1</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span>
 </span><span class="line" id="L66"><span class="nc_i nc_v popupable" title="c: C" data-content="&lt;div&gt;&lt;b&gt;local var&lt;&#47;b&gt; &lt;span&gt;c:&lt;a href=&#34;#base_simple3___base_simple3__C&#34;&gt;base_simple3$C&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">c</span><span class="popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$C$val2" data-title="&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;call base_simple3$C$val2&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__C___val2&#34;&gt;base_simple3$C$val2&lt;&#47;a&gt;&lt;span&gt;: &lt;a href=&#34;#base_simple3___base_simple3__Int&#34;&gt;base_simple3$Int&lt;&#47;a&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">val2</span><span class="popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">.</span><span class="nc_i popupable" title="call base_simple3$Int$output" data-title="&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;call base_simple3$Int$output&lt;&#47;a&gt;" data-content="&lt;div&gt;&lt;b&gt;call&lt;&#47;b&gt; &lt;span&gt;&lt;a href=&#34;#base_simple3___base_simple3__Int___output&#34;&gt;base_simple3$Int$output&lt;&#47;a&gt;&lt;span&gt;&lt;&#47;span&gt;&lt;&#47;span&gt;&lt;br&#47;&gt;&lt;&#47;div&gt;" data-toggle="popover">output</span></span></span></span></code></pre>
 <h2>AST node: ANoImport at base_simple3.nit:17,1--10</h2>
 <pre><code><span class="nitcode"><span class="line" id="L26"> <span class="nc_k">is</span></span></span></code></pre>
 <h2>AST node: AAnnotation at base_simple3.nit:26,16--21</h2>
 <pre><code><span class="nitcode"><span class="line" id="L26"> <span class="nc_i">intern</span></span></span></code></pre>
-<h2>AST node: AIdAtid at base_simple3.nit:26,16--21</h2>
-<pre><code><span class="nitcode"><span class="line" id="L26"> <span class="nc_i">intern</span></span></span></code></pre>
-<h2>AST node: AConcreteClasskind at base_simple3.nit:29,1--5</h2>
-<pre><code><span class="nitcode"><span class="line" id="L29"><span class="nc_k">class</span></span></span></code></pre>
-<h2>AST node: TKwclass at base_simple3.nit:29,1--5</h2>
-<pre><code><span class="nitcode"><span class="line" id="L29"><span class="nc_k">class</span></span></span></code></pre>
-<h2>AST node: TKwinit at base_simple3.nit:30,2--5</h2>
-<pre><code><span class="nitcode"><span class="nc_pdef foldable" id="base_simple3$A$init"><span class="line" id="L30">  <span class="nc_k">init</span></sp***TRUNCATED***
+<h2>AST node: AIdAtid at bas***TRUNCATED***
index d68740c..a6058fd 100644 (file)
@@ -1,12 +1,3 @@
-# elfves
+# elf
 
- * 4: Elf (test_prog::Elf)
- * 5: Sys (test_prog::Sys)
- * 5: careers (test_prog::careers)
- * 5: examples (test_prog>examples>)
- * 5: excluded (excluded>)
- * 5: excluded (excluded)
- * 5: excluded (excluded::excluded)
- * 5: game (test_prog>game>)
- * 5: game (test_prog::game)
- * 4: races (test_prog::races)
+ * 1: Elf (test_prog::Elf)
index 02cba00..b8eaa33 100644 (file)
@@ -1,12 +1,3 @@
-# Dwarves
+# test_prog::Dwarv
 
- * 12: Sys (test_prog::Sys)
- * 8: excluded (excluded>)
- * 7: excluded (excluded)
- * 13: game (test_prog>game>)
- * 13: man (test_prog>man>)
- * 13: races (test_prog::races)
- * 13: rpg (test_prog>rpg>)
- * 13: rpg (test_prog::rpg)
- * 9: test_prog (test_prog)
- * 9: test_prog (test_prog>)
+ * 1: Dwarf (test_prog::Dwarf)
index b1ae3db..492b372 100644 (file)
@@ -1,12 +1,3 @@
-# test_prof::Dwarves
+# test_prof::Dwarf
 
- * 5: Career (test_prog::Career)
- * 4: Dwarf (test_prog::Dwarf)
- * 6: Game (test_prog::Game)
- * 6: Race (test_prog::Race)
- * 5: Starter (test_prog::Starter)
- * 5: careers (test_prog::careers)
- * 7: character (test_prog::character)
- * 6: game (test_prog::game)
- * 5: races (test_prog::races)
- * 7: rpg (test_prog::rpg)
+ * 1: Dwarf (test_prog::Dwarf)
index fe5bfd3..62bdafb 100644 (file)
@@ -1,12 +1,3 @@
 # Obj
 
- * 3: + (test_prog::Int::+)
- * 3: > (test_prog::Int::>)
- * 3: Elf (test_prog::Elf)
- * 3: Int (test_prog::Int)
  * 1: Object (test_prog::Object)
- * 3: Sys (test_prog::Sys)
- * 3: age (test_prog::Character::age)
- * 3: man (test_prog>man>)
- * 3: rpg (test_prog::rpg)
- * 3: rpg (test_prog>rpg>)
index 3fa271e..806088f 100644 (file)
@@ -1,12 +1,12 @@
 # C
 
- * 1: * (test_prog::Float::*)
  * 1: * (test_prog::Int::*)
+ * 1: * (test_prog::Float::*)
+ * 1: + (test_prog::Int::+)
  * 1: + (test_prog::Float::+)
- * 1: - (test_prog::Int::-)
  * 1: - (test_prog::Float::-)
+ * 1: - (test_prog::Int::-)
  * 1: / (test_prog::Float::/)
  * 1: / (test_prog::Int::/)
- * 1: > (test_prog::Int::>)
  * 1: > (test_prog::Float::>)
  * 1: Career (test_prog::Career)
index 65b6c73..dda5763 100644 (file)
@@ -1,12 +1,6 @@
 # to
 
- * 2: * (test_prog::Float::*)
- * 2: + (test_prog::Float::+)
- * 2: - (test_prog::Float::-)
- * 2: / (test_prog::Float::/)
- * 2: / (test_prog::Int::/)
- * 2: == (test_prog::Object::==)
- * 2: > (test_prog::Int::>)
- * 2: > (test_prog::Float::>)
  * 1: to_f (test_prog::Int::to_f)
+ * 3: total_endurance (test_prog::Character::total_endurance)
+ * 4: total_intelligence (test_prog::Character::total_intelligence)
  * 2: total_strengh (test_prog::Character::total_strengh)
index bd3e0ad..7e420df 100644 (file)
@@ -1,12 +1,3 @@
-# Dwa
+# test_prog::Dwar
 
- * 13: Dwarf (test_prog::Dwarf)
- * 9: excluded (excluded>)
- * 8: excluded (excluded)
- * 14: game (test_prog>game>)
- * 14: game (test_prog::game)
- * 13: man (test_prog>man>)
- * 14: rpg (test_prog>rpg>)
- * 14: rpg (test_prog::rpg)
- * 10: test_prog (test_prog>)
- * 9: test_prog (test_prog)
+ * 1: Dwarf (test_prog::Dwarf)
index 89e9bc8..5ee70f9 100644 (file)
@@ -3,10 +3,10 @@
  * 1: Career (test_prog::Career)
  * 2: Character (test_prog::Character)
  * 3: Combatable (test_prog::Combatable)
- * 3: Elf (test_prog::Elf)
- * 3: Int (test_prog::Int)
- * 3: Sys (test_prog::Sys)
- * 4: game (test_prog::game)
- * 3: rpg (test_prog::rpg)
- * 3: test_prog (test_prog)
- * 3: test_prog (test_prog>)
+ * 4: age (test_prog::Character::age)
+ * 8: name (test_prog::Character::name)
+ * 7: quit (test_prog::Character::quit)
+ * 6: race (test_prog::Character::race)
+ * 5: sex (test_prog::Character::sex)
+ * 9: age= (test_prog::Character::age=)
+ * 10: sex= (test_prog::Character::sex=)
index 3fa271e..806088f 100644 (file)
@@ -1,12 +1,12 @@
 # C
 
- * 1: * (test_prog::Float::*)
  * 1: * (test_prog::Int::*)
+ * 1: * (test_prog::Float::*)
+ * 1: + (test_prog::Int::+)
  * 1: + (test_prog::Float::+)
- * 1: - (test_prog::Int::-)
  * 1: - (test_prog::Float::-)
+ * 1: - (test_prog::Int::-)
  * 1: / (test_prog::Float::/)
  * 1: / (test_prog::Int::/)
- * 1: > (test_prog::Int::>)
  * 1: > (test_prog::Float::>)
  * 1: Career (test_prog::Career)
index d2cf349..dda5763 100644 (file)
@@ -1,12 +1,6 @@
 # to
 
- * 2: * (test_prog::Int::*)
- * 2: * (test_prog::Float::*)
- * 2: + (test_prog::Float::+)
- * 2: - (test_prog::Float::-)
- * 2: / (test_prog::Float::/)
- * 2: / (test_prog::Int::/)
- * 2: > (test_prog::Float::>)
- * 2: > (test_prog::Int::>)
  * 1: to_f (test_prog::Int::to_f)
+ * 3: total_endurance (test_prog::Character::total_endurance)
+ * 4: total_intelligence (test_prog::Character::total_intelligence)
  * 2: total_strengh (test_prog::Character::total_strengh)
index 41184bb..735e8ba 100644 (file)
@@ -1,12 +1,3 @@
-# Foo
+# Floot
 
- * 3: * (test_prog::Int::*)
- * 2: Bool (test_prog::Bool)
- * 3: Elf (test_prog::Elf)
- * 3: Float (test_prog::Float)
- * 3: Int (test_prog::Int)
- * 3: Sys (test_prog::Sys)
- * 3: dps (test_prog::Weapon::dps)
- * 3: man (test_prog>man>)
- * 3: rpg (test_prog>rpg>)
- * 3: rpg (test_prog::rpg)
+ * 1: Float (test_prog::Float)
index 0c44100..5ee70f9 100644 (file)
@@ -3,10 +3,10 @@
  * 1: Career (test_prog::Career)
  * 2: Character (test_prog::Character)
  * 3: Combatable (test_prog::Combatable)
- * 3: Elf (test_prog::Elf)
- * 3: Int (test_prog::Int)
- * 3: Sys (test_prog::Sys)
- * 3: rpg (test_prog::rpg)
- * 3: test_prog (test_prog>)
- * 3: test_prog (test_prog)
- * 3: test_prog (test_prog::test_prog)
+ * 4: age (test_prog::Character::age)
+ * 8: name (test_prog::Character::name)
+ * 7: quit (test_prog::Character::quit)
+ * 6: race (test_prog::Character::race)
+ * 5: sex (test_prog::Character::sex)
+ * 9: age= (test_prog::Character::age=)
+ * 10: sex= (test_prog::Character::sex=)
index 6381895..0b99c62 100644 (file)
@@ -4,8 +4,8 @@
  * 1: * (test_prog::Int::*)
  * 1: + (test_prog::Int::+)
  * 1: + (test_prog::Float::+)
- * 1: - (test_prog::Int::-)
  * 1: - (test_prog::Float::-)
+ * 1: - (test_prog::Int::-)
  * 1: / (test_prog::Int::/)
  * 1: / (test_prog::Float::/)
  * 1: > (test_prog::Int::>)
index d8bc532..735e8ba 100644 (file)
@@ -1,12 +1,3 @@
-# Foo
+# Floot
 
- * 2: Bool (test_prog::Bool)
- * 3: Elf (test_prog::Elf)
- * 3: Float (test_prog::Float)
- * 3: Int (test_prog::Int)
- * 3: Sys (test_prog::Sys)
- * 3: age (test_prog::Character::age)
- * 3: dps (test_prog::Weapon::dps)
- * 3: man (test_prog>man>)
- * 3: rpg (test_prog::rpg)
- * 3: rpg (test_prog>rpg>)
+ * 1: Float (test_prog::Float)
index 02b60bc..742b701 100644 (file)
@@ -1,5 +1,5 @@
 CString
-0x4e
+78
 Nit
 NativeArray[Int]
 3
index c36446c..1af51e8 100644 (file)
@@ -1,4 +1,4 @@
 Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/core/collection/array.nit:991)
 CString
-0x4e
+78
 Nit
index 9ee42f3..6a13937 100644 (file)
@@ -128,3 +128,10 @@ Content-Length: 0
 Server: nitcorn\r
 Set-Cookie: nitcorn_session=; HttpOnly; expires=Thu, 01 Jan 1970 00:00:00 GMT\r
 \r
+
+[Client] curl -s localhost:*****/simple_binary/
+ñòó
+
+[Client] curl -s localhost:*****/simple_template/
+Hello
+ñòó
diff --git a/tests/sav/test_prefixed_chars_alt1.res b/tests/sav/test_prefixed_chars_alt1.res
deleted file mode 100644 (file)
index 8c96895..0000000
+++ /dev/null
@@ -1 +0,0 @@
-alt/test_prefixed_chars_alt1.nit:18,17--20: Syntax Error: usage of byte prefix on multibyte character.
index a61d3e4..ac57a1c 100644 (file)
@@ -1,2 +1,2 @@
 à1111111111111111111111111111111111111111éć2222222222222222222222222222222222222222ç
-0xc3 0xa0 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0xc3 0xa9 0xc4 0x87 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0x32 0xc3 0xa7
+195 160 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 195 169 196 135 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 195 167
index 8e3a30b..e6f0a3d 100644 (file)
@@ -1,8 +1,8 @@
-[0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c]
-[0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c]
-[0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c,0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c]
-[0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54]
-[0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54]
-[0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54,0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54]
-[0x54,0x68,0x69,0x73,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x69,0x73,0x20,0x63,0x6f,0x6f,0x6c]
-[0x6c,0x6f,0x6f,0x63,0x20,0x73,0x69,0x20,0x67,0x6e,0x69,0x72,0x74,0x73,0x20,0x73,0x69,0x68,0x54]
+[84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108]
+[84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108]
+[84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108,84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108]
+[108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84]
+[108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84]
+[108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84,108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84]
+[84,104,105,115,32,115,116,114,105,110,103,32,105,115,32,99,111,111,108]
+[108,111,111,99,32,115,105,32,103,110,105,114,116,115,32,115,105,104,84]
index 7970971..e0923ae 100644 (file)
@@ -32,7 +32,7 @@ end
 var w = args.first.to_i
 var h = w
 
-var byte_acc = 0u8
+var byte_acc = 0
 var bit_num = 0
 
 print("P4\n{w} {h}")
@@ -56,19 +56,19 @@ for y in [0..h[ do
        if zr*zr+zi*zi > limit*limit then
            byte_acc = byte_acc << 1
        else
-           byte_acc = (byte_acc << 1) + 1u8
+           byte_acc = (byte_acc << 1) + 1
        end
 
        bit_num = bit_num + 1
 
        if bit_num == 8 then
            stdout.write_byte(byte_acc)
-           byte_acc = 0u8
+           byte_acc = 0
            bit_num = 0     
        else if x == w - 1 then
            byte_acc = byte_acc << (8-w%8)
            stdout.write_byte(byte_acc)
-           byte_acc = 0u8
+           byte_acc = 0
            bit_num = 0     
        end
     end
index 6a05c79..73b3ee6 100644 (file)
@@ -17,20 +17,20 @@ class Bitarray
        var narr: Bytes
 
        init do
-               for x in [0 .. narr.length[ do narr[x] = 0xFFu8
+               for x in [0 .. narr.length[ do narr[x] = 0xFF
        end
 
        fun [](pos: Int): Bool do
                pos -= 2
-               return (narr[pos / 8] & (1u8 << (7 - pos % 8))) != 0u8
+               return (narr[pos / 8] & (1 << (7 - pos % 8))) != 0
        end
 
        fun []=(pos: Int, val: Bool) do
                pos -= 2
                if val then
-                       narr[pos / 8] |= 1u8 << (7 - pos % 8)
+                       narr[pos / 8] |= 1 << (7 - pos % 8)
                else
-                       narr[pos / 8] &= 0xFFu8 - (1u8 << (7 - pos % 8))
+                       narr[pos / 8] &= 0xFF - (1 << (7 - pos % 8))
                end
        end
 end
index a1b5400..3d2a47a 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var c1 = b'G'
+var c1 = u'G'
 var c2 = u'𐏓'
 
 var s = b"String\x41\x42"
index 45750de..f4b7a3f 100644 (file)
@@ -19,7 +19,7 @@ var writer = new FileWriter.open(path)
 #alt1# writer.big_endian = false
 #alt3# writer.big_endian = false
 writer.write "hello"
-writer.write_byte 77u8
+writer.write_byte 77
 writer.write_float 1.23456789
 writer.write_double 1.23456789
 writer.write_int64 123456789
index c42de6d..5ce1a1f 100644 (file)
@@ -34,7 +34,7 @@ end
 l = 0
 
 for i in fb.bytes do
-       print "Byte {l} = {i}"
+       print "Byte {l} = 0x{i.to_hex}"
        l += 1
 end
 
@@ -48,6 +48,6 @@ end
 l = fb.byte_length - 1
 
 for i in fb.bytes.reverse_iterator do
-       print "Byte {l} = {i}"
+       print "Byte {l} = 0x{i.to_hex}"
        l -= 1
 end
index 42795f4..dd52ec3 100644 (file)
@@ -19,7 +19,7 @@ import pthreads
 class CatchThread
        super Thread
 
-       var x = 100000
+       var x = 10000
        var caught = 0
 
        redef fun main do
index ac86448..7bce83b 100644 (file)
@@ -1,21 +1,21 @@
-test_prog Obj --name-prefix --no-color
-test_prog C --name-prefix --no-color
-test_prog e --name-prefix --no-color
-test_prog to --name-prefix --no-color
-test_prog C --full-name-prefix --no-color
-test_prog test_prog:: --full-name-prefix --no-color
-test_prog test_prog::C --full-name-prefix --no-color
-test_prog A --name-similarity --no-color
-test_prog Foo --name-similarity --no-color
-test_prog elfves --name-similarity --no-color
-test_prog Dwarves --full-name-similarity --no-color
-test_prog test_prof::Dwarves --full-name-similarity --no-color
-test_prog Obj --name --no-color
-test_prog C --name --no-color
-test_prog to --name --no-color
-test_prog Dwa --full-name --no-color
-test_prog test_prog::C --full-name --no-color
-test_prog C --no-color
-test_prog to --no-color
-test_prog Foo --no-color
-test_prog test_prog::C --no-color
+test_prog -q Obj --name-prefix --no-color
+test_prog -q C --name-prefix --no-color
+test_prog -q e --name-prefix --no-color
+test_prog -q to --name-prefix --no-color
+test_prog -q C --full-name-prefix --no-color
+test_prog -q test_prog:: --full-name-prefix --no-color
+test_prog -q test_prog::C --full-name-prefix --no-color
+test_prog -q A --name-similarity --no-color
+test_prog -q Floot --name-similarity --no-color
+test_prog -q elf --name-similarity --no-color
+test_prog -q test_prog::Dwarv --full-name-similarity --no-color
+test_prog -q test_prof::Dwarf --full-name-similarity --no-color
+test_prog -q Obj --name --no-color
+test_prog -q C --name --no-color
+test_prog -q to --name --no-color
+test_prog -q test_prog::Dwar --full-name --no-color
+test_prog -q test_prog::C --full-name --no-color
+test_prog -q C --no-color
+test_prog -q to --no-color
+test_prog -q Floot --no-color
+test_prog -q test_prog::C --no-color
index e6fee68..39400dc 100644 (file)
 # limitations under the License.
 
 var s = new CString(4)
-s[0] = 0x4Eu8
-s[2] = 0x74u8
-s[1] = 0x69u8
-s[3] = 0u8
+s[0] = 0x4E
+s[2] = 0x74
+s[1] = 0x69
+s[3] = 0
 print s.class_name
 print s[0]
 print s.to_s
index b7fcd90..7f9c9d6 100644 (file)
@@ -30,23 +30,49 @@ class MyAction
        redef fun answer(request, turi)
        do
                var rep = new HttpResponse(200)
-               rep.body = """
+               var body = """
 [Response] Simple answer
 Method: {{{request.method}}}, URI: {{{request.uri}}}, trailing: {{{turi}}}"""
 
                if request.get_args.not_empty
-               then rep.body += "\nGET args: {request.get_args.join(", ", ":")}"
+               then body += "\nGET args: {request.get_args.join(", ", ":")}"
 
                if request.post_args.not_empty
-               then rep.body += "\nPOST args: {request.post_args.join(", ", ":")}"
+               then body += "\nPOST args: {request.post_args.join(", ", ":")}"
 
                if request.uri_params.not_empty
-               then rep.body += "\nParams args: {request.uri_params.join(", ", ":")}"
+               then body += "\nParams args: {request.uri_params.join(", ", ":")}"
 
                if request.cookie.not_empty
-               then rep.body += "\nCookie: {request.cookie.join(", ", ":")}"
+               then body += "\nCookie: {request.cookie.join(", ", ":")}"
 
-               rep.body += "\n"
+               body += "\n"
+               rep.body = body
+               return rep
+       end
+end
+
+class MyBinAction
+       super Action
+
+       redef fun answer(request, turi)
+       do
+               var rep = new HttpResponse(200)
+               rep.body = b"\xF1\xF2\xF3\n"
+               return rep
+       end
+end
+
+class MyTmplAction
+       super Action
+
+       redef fun answer(request, turi)
+       do
+               var rep = new HttpResponse(200)
+               var body = new Template
+               body.add "Hello\n"
+               body.add b"\xF1\xF2\xF3\n"
+               rep.body = body
                return rep
        end
 end
@@ -64,6 +90,8 @@ class ServerThread
                vh.routes.add new Route("file_server", new FileServer(fs_path.simplify_path))
                vh.routes.add new Route("simple_answer", new MyAction)
                vh.routes.add new Route("params_answer/:i/:s", new MyAction)
+               vh.routes.add new Route("simple_binary", new MyBinAction)
+               vh.routes.add new Route("simple_template", new MyTmplAction)
 
                # Launch
                var factory = new HttpFactory.and_libevent
@@ -104,6 +132,9 @@ class ClientThread
                system "curl -s {iface}/file_server/unknown_file.txt --head"
 
                system "curl -s {iface}/invalid_route --head"
+
+               system "curl -s {iface}/simple_binary/"
+               system "curl -s {iface}/simple_template/"
                return null
        end
 
index e3b3301..64bc744 100644 (file)
 # limitations under the License.
 
 # a 'success' unit test (pass)
+#
 #     assert true
 module test_nitunit
 # a 'error' unit test (do not pass)
+#
 #     assert false
 class X
        # a 'failure' unit test (does not compile)
+       #
        #     assert undefined_identifier
        fun foo do end
 
        # a 'failure' unit test (does not parse)
+       #
        #     assert !@#$%^&*()
        fun foo1(a, b: Int) do end
 
index 3070060..a963e75 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var ascii_char = b'A'
+var ascii_char = u'A'
 var unicode_char = u'𐏓'
 
-#alt1 var bug_ascii = b'𐏓'
-
 print ascii_char
 print unicode_char
index 61b00e9..7740b5f 100755 (executable)
 # limitations under the License.
 
 # Run some tests on each engine
-for x in nitcg nitcs nitcsg nitce niti nitvm; do
+
+engine=(nitcg nitcg nitcs nitcsg nitce niti nitvm)
+if uname | grep MINGW64 1>/dev/null 2>&1; then
+       engine=(nitcg nitcg nitcs nitcsg nitce)
+fi
+
+for x in "${engine[@]}"; do
        echo "--engine $x"
        ./tests.sh --engine $x "$@"
 done