+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Transform Nit verbatim documentation into HTML
-module docdown
-
-private import parser
-import html
-private import highlight
-private import parser_util
-
-# The class that does the convertion from a `ADoc` to HTML
-private class Doc2Mdwn
- var toolcontext: ToolContext
-
- # The lines of the current code block, empty is no current code block
- var curblock = new Array[String]
-
- # Count empty lines between code blocks
- var empty_lines = 0
-
- # Optional tag for a fence
- var fence_tag = ""
-
- fun work(mdoc: MDoc): HTMLTag
- do
- var root = new HTMLTag("div")
- root.add_class("nitdoc")
-
- # Indent level of the previous line
- var lastindent = 0
-
- # Indent level of the current line
- var indent = 0
-
- # Expected fencing closing tag (if any)
- var in_fence: nullable String = null
-
- # The current element (p, li, etc.) if any
- var n: nullable HTMLTag = null
-
- # The current ul element (if any)
- var ul: nullable HTMLTag = null
-
- var is_first_line = true
- # Local variable to benefit adaptive typing
- for text in mdoc.content do
- # Count the number of spaces
- lastindent = indent
- indent = 0
- while text.length > indent and text.chars[indent] == ' ' do indent += 1
-
- # In a fence
- if in_fence != null then
- # fence closing
- if text.substring(0,in_fence.length) == in_fence then
- close_codeblock(n or else root)
- in_fence = null
- continue
- end
- # else fence content
- curblock.add(text)
- continue
- end
-
- # Is codeblock? Then just collect them
- if indent >= 3 then
- for i in [0..empty_lines[ do curblock.add("")
- empty_lines = 0
- # to allows 4 spaces including the one that follows the #
- curblock.add(text)
- fence_tag = ""
- continue
- end
-
- # fence opening
- if text.substring(0,3) == "~~~" then
- # Was a codblock just before the current line ?
- close_codeblock(n or else root)
-
- var l = 3
- while l < text.length and text.chars[l] == '~' do l += 1
- in_fence = text.substring(0, l)
- while l < text.length and (text.chars[l] == '.' or text.chars[l] == ' ') do l += 1
- fence_tag = text.substring_from(l)
- continue
- end
-
- # Cleanup the string
- text = text.trim
-
- # The HTML node of the last line, so we know if we continue the same block
- var old = n
-
- # No line or loss of indentation: reset
- if text.is_empty or indent < lastindent then
- n = null
- ul = null
- if text.is_empty then
- if not curblock.is_empty then empty_lines += 1
- continue
- end
- end
-
- # Was a codblock just before the current line ?
- close_codeblock(n or else root)
-
- # Special first word: new paragraph
- if text.has_prefix("TODO") or text.has_prefix("FIXME") then
- n = new HTMLTag("p")
- root.add n
- n.add_class("todo")
- ul = null
- else if text.has_prefix("REQUIRE") or text.has_prefix("Require") or text.has_prefix("ENSURE") or text.has_prefix("Ensure") then
- n = new HTMLTag("p")
- root.add n
- n.add_class("contract")
- ul = null
- end
-
- # List
- if text.has_prefix("* ") or text.has_prefix("- ") then
- text = text.substring_from(1).trim
- if ul == null then
- ul = new HTMLTag("ul")
- root.add ul
- end
- n = new HTMLTag("li")
- ul.add(n)
- end
-
- # Nothing? then paragraph
- if n == null then
- n = new HTMLTag("p")
- root.add n
- ul = null
- end
-
- if old == n then
- # Because spaces and `\n` where trimmed
- n.append("\n")
- end
-
- process_line(n, text)
-
- # Special case, the fist line is the synopsys and is in its own paragraph
- if is_first_line then
- n.add_class("synopsys")
- n = null
- is_first_line = false
- end
- end
-
- # If the codeblock was the last code sequence
- close_codeblock(n or else root)
-
- return root
- end
-
- fun short_work(mdoc: MDoc): HTMLTag
- do
- var text = mdoc.content.first
- var n = new HTMLTag("span")
- n.add_class("synopsys")
- n.add_class("nitdoc")
- process_line(n, text)
- return n
- end
-
- fun process_line(n: HTMLTag, text: String)
- do
- # Loosly detect code parts
- var parts = text.split("`")
-
- # Process each code parts, thus alternate between text and code
- var is_text = true
- for part in parts do
- if is_text then
- # Text part
- n.append part
- else
- # Code part
- var n2 = new HTMLTag("code")
- n.add(n2)
- process_code(n2, part, null)
- end
- is_text = not is_text
- end
- end
-
- fun close_codeblock(root: HTMLTag)
- do
- # Is there a codeblock to manage?
- if not curblock.is_empty then
- empty_lines = 0
-
- # determine the smalest indent
- var minindent = -1
- for text in curblock do
- var indent = 0
- while indent < text.length and text.chars[indent] == ' ' do indent += 1
- # skip white lines
- if indent >= text.length then continue
- if minindent == -1 or indent < minindent then
- minindent = indent
- end
- end
- if minindent < 0 then minindent = 0
-
- # Generate the text
- var btext = new FlatBuffer
- for text in curblock do
- btext.append text.substring_from(minindent)
- btext.add '\n'
- end
-
- # add the node
- var n = new HTMLTag("pre")
- root.add(n)
- process_code(n, btext.to_s, fence_tag)
- curblock.clear
- end
- end
-
- fun process_code(n: HTMLTag, text: String, tag: nullable String)
- do
- # Do not try to highlight non-nit code.
- if tag != null and tag != "" and tag != "nit" and tag != "nitish" then
- n.append text
- n.add_class("rawcode")
- return
- end
-
- # Try to parse it
- var ast = toolcontext.parse_something(text)
-
- if ast isa AError then
- n.append text
- # n.attrs["title"] = ast.message
- n.add_class("rawcode")
- else
- var v = new HighlightVisitor
- v.enter_visit(ast)
- n.add(v.html)
- n.add_class("nitcode")
- end
- end
-end
-
-redef class MDoc
- # Build a `<div>` element that contains the full documentation in HTML
- fun full_markdown: HTMLTag
- do
- var res = full_markdown_cache
- if res != null then return res
- var tc = new ToolContext
- var d2m = new Doc2Mdwn(tc)
- res = d2m.work(self)
- full_markdown_cache = res
- return res
- end
-
- private var full_markdown_cache: nullable HTMLTag
-
- # Build a `<span>` element that contains the synopsys in HTML
- fun short_markdown: HTMLTag
- do
- var res = short_markdown_cache
- if res != null then return res
- var tc = new ToolContext
- var d2m = new Doc2Mdwn(tc)
- res = d2m.short_work(self)
- short_markdown_cache = res
- return res
- end
-
- private var short_markdown_cache: nullable HTMLTag
-end
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Program to test the `markdown` module on real source files.
-module test_docdown
-
-import modelize
-import highlight
-import docdown
-
-redef class ModelBuilder
- fun do_test_markdown(page: HTMLTag, mmodule: MModule)
- do
- page.add_raw_html "<h3 id='{mmodule}'>module {mmodule}</h1>"
- var mdoc = mmodule.mdoc
- if mdoc != null then
- page.add mdoc.full_markdown
- end
- for mclassdef in mmodule.mclassdefs do
- mdoc = mclassdef.mdoc
- if mdoc != null then
- page.add_raw_html "<h4 id='{mclassdef}'>class {mclassdef}</h2>"
- page.add mdoc.full_markdown
- end
- for mpropdef in mclassdef.mpropdefs do
- mdoc = mpropdef.mdoc
- if mdoc != null then
- page.add_raw_html "<h5 id='{mpropdef}'>prop {mpropdef}</h3>"
- page.add mdoc.full_markdown
- end
- end
- end
- end
-end
-
-redef class MModule
- redef fun href do return "#{to_s}"
-end
-redef class MClassDef
- redef fun href do return "#{to_s}"
-end
-redef class MPropDef
- redef fun href do return "#{to_s}"
-end
-
-var toolcontext = new ToolContext
-
-var opt_full = new OptionBool("Process also imported modules", "--full")
-toolcontext.option_context.add_option(opt_full)
-toolcontext.tooldescription = "Usage: test_markdown [OPTION]... <file.nit>...\nGenerates HTML of comments of documentation from Nit source files."
-
-toolcontext.process_options(args)
-var args = toolcontext.option_context.rest
-
-var model = new Model
-var modelbuilder = new ModelBuilder(model, toolcontext)
-
-var mmodules = modelbuilder.parse(args)
-modelbuilder.run_phases
-
-var hv = new HighlightVisitor
-
-var page = new HTMLTag("html")
-page.add_raw_html """
-<head>
-<meta charset="utf-8">
-"""
-page.add_raw_html hv.head_content
-page.add_raw_html """
-<style type="text/css">
-code {margin: 0 2px;
-padding: 0px 5px;
-border: 1px solid #ddd;
-background-color: #f8f8f8;
-border-radius: 3px;}
-pre {
-background-color: #f8f8f8;
-border: 1px solid #ddd;
-font-size: 13px;
-line-height: 19px;
-overflow: auto;
-padding: 6px 6px;
-border-radius: 3px;
-}
-.rawcode[title] {
-border-color: red;
-}
-h5 {font-weight:bold;}
-{{{hv.css_content}}}
-</style>
-</head><body>"""
-
-if opt_full.value then
- for p in model.mprojects do
- page.add_raw_html "<h1 id='P{p.name}'>project {p.name}</h2>"
- var mdoc = p.mdoc
- if mdoc != null then
- page.add mdoc.full_markdown
- end
- for g in p.mgroups do
- mdoc = g.mdoc
- if mdoc != null then
- page.add_raw_html "<h2 id='G{g.full_name}'>group {g.full_name}</h2>"
- page.add mdoc.full_markdown
- end
- for m in g.mmodules do
- modelbuilder.do_test_markdown(page, m)
- end
- end
- end
-else
- for m in mmodules do
- modelbuilder.do_test_markdown(page, m)
- end
-end
-
-page.add_raw_html hv.foot_content
-page.add_raw_html "</body>"
-page.write_to(stdout)
+++ /dev/null
-Usage: test_markdown [OPTION]... <file.nit>...
-Generates HTML of comments of documentation from Nit source files.
-Use --help for help
+++ /dev/null
-<html><head>
-<meta charset="utf-8">
-<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
-<style type="text/css">
-code {margin: 0 2px;
-padding: 0px 5px;
-border: 1px solid #ddd;
-background-color: #f8f8f8;
-border-radius: 3px;}
-pre {
-background-color: #f8f8f8;
-border: 1px solid #ddd;
-font-size: 13px;
-line-height: 19px;
-overflow: auto;
-padding: 6px 6px;
-border-radius: 3px;
-}
-.rawcode[title] {
-border-color: red;
-}
-h5 {font-weight:bold;}
-.nitcode a { color: inherit; cursor:pointer; }
-.nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
-.nitcode .foldable { display: block } /* for block productions*/
-.nitcode .line{ display: block } /* for lines */
-.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
-.nitcode :target { background-color: #FFF3C2 } /* target highlight*/
-/* 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 */
-.popover { max-width: 800px !important; }
-
-</style>
-</head><body><h3 id='test_doc'>module test_doc</h1><h4 id='test_doc#A'>class test_doc#A</h2><div class="nitdoc"><p class="synopsys">Synopsys</p><p>Paragraph
-same paragraph</p><p>Other paragraph with <code class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_i">code</span><span></span></span></span></code></p><ul><li>bullet</li><li>other buller</li><li>last
-but long
-bullet</li></ul><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_i">some</span>
-</span><span class="line" id="L2"><span class="nc_i">block</span>
-</span><span class="line" id="L3"><span></span></span></span></pre><p>a first example</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_l">1</span> <span class="nc_o">+</span> <span class="nc_l">1</span> <span class="nc_o">==</span> <span class="nc_l">2</span>
-</span><span class="line" id="L2"><span></span></span></span></pre><p>and a last example to illustrate the <code class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_i">to_s</span><span></span></span></span></code> method on <code class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_t">A</span><span></span></span></span></code>.</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">var</span> <span class="nc_i">a</span> <span>=</span> <span class="nc_k">new</span> <span class="nc_t">A</span>
-</span><span class="line" id="L2"><span class="nc_k">assert</span> <span class="nc_i">a</span><span>.</span><span class="nc_i">to_s</span> <span class="nc_o">==</span> <span class="nc_s">"A"</span>
-</span><span class="line" id="L3"><span></span></span></span></pre></div><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
+++ /dev/null
-<html><head>
-<meta charset="utf-8">
-<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
-<style type="text/css">
-code {margin: 0 2px;
-padding: 0px 5px;
-border: 1px solid #ddd;
-background-color: #f8f8f8;
-border-radius: 3px;}
-pre {
-background-color: #f8f8f8;
-border: 1px solid #ddd;
-font-size: 13px;
-line-height: 19px;
-overflow: auto;
-padding: 6px 6px;
-border-radius: 3px;
-}
-.rawcode[title] {
-border-color: red;
-}
-h5 {font-weight:bold;}
-.nitcode a { color: inherit; cursor:pointer; }
-.nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
-.nitcode .foldable { display: block } /* for block productions*/
-.nitcode .line{ display: block } /* for lines */
-.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
-.nitcode :target { background-color: #FFF3C2 } /* target highlight*/
-/* 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 */
-.popover { max-width: 800px !important; }
-
-</style>
-</head><body><h3 id='test_doc2'>module test_doc2</h1><h5 id='test_doc2#Sys#foo1'>prop test_doc2#Sys#foo1</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
-</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Sys#foo2'>prop test_doc2#Sys#foo2</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
-</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Sys#foo3'>prop test_doc2#Sys#foo3</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
-</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Sys#foo4'>prop test_doc2#Sys#foo4</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="rawcode">assert false # not tested (and not highlighted)
-</pre></div><h5 id='test_doc2#Sys#foo5'>prop test_doc2#Sys#foo5</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">false</span> <span># not tested (but highlighted)
-</span></span><span class="line" id="L2"><span></span></span></span></pre></div><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