sep_comp: SeparateRuntimeFunction::compile_to_c only declare if module is dead
[nit.git] / src / doc / doc_down.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Handle markdown formatting in Nit comments.
16 module doc_down
17
18 import markdown
19 import highlight
20 private import parser_util
21
22 redef class MDoc
23 # Comment synopsys HTML escaped
24 var short_comment: String is lazy do return content.first.html_escape
25
26 # Full comment HTML escaped
27 var full_comment: String is lazy do return content.join("\n").html_escape
28
29 private var markdown_proc: MarkdownProcessor is lazy do
30 return original_mentity.model.nitdoc_md_processor
31 end
32
33 private var inline_proc: MarkdownProcessor is lazy do
34 return original_mentity.model.nitdoc_inline_processor
35 end
36
37 # Synopsys in a template
38 var tpl_short_comment: Writable is lazy do
39 var res = new Template
40 var syn = inline_proc.process(content.first)
41 res.add "<span class=\"synopsys nitdoc\">{syn}</span>"
42 return res
43
44 end
45
46 # Full comment in a template
47 var tpl_comment: Writable is lazy do
48 var res = new Template
49 var lines = content.to_a
50 res.add "<div class=\"nitdoc\">"
51 # do not use DocUnit as synopsys
52 if not content.first.has_prefix(" ") and
53 not content.first.has_prefix("\t") then
54 # parse synopsys
55 var syn = inline_proc.process(lines.shift)
56 res.add "<p class=\"synopsys\">{syn}</p>"
57 end
58 # check for annotations
59 for i in [0 .. lines.length[ do
60 var line = lines[i]
61 if line.to_upper.has_prefix("ENSURE") or line.to_upper.has_prefix("REQUIRE") then
62 var html = inline_proc.process(line)
63 lines[i] = "<p class=\"contract\">{html}</p>"
64 else if line.to_upper.has_prefix("TODO") or line.to_upper.has_prefix("FIXME") then
65 var html = inline_proc.process(line)
66 lines[i] = "<p class=\"todo\">{html}</p>"
67 end
68 end
69 # add other lines
70 res.add markdown_proc.process(lines.join("\n"))
71 res.add "</div>"
72 return res
73 end
74 end
75
76 private class NitdocDecorator
77 super HTMLDecorator
78
79 var toolcontext = new ToolContext
80
81 redef fun add_code(v, block) do
82 var meta = "nit"
83 if block isa BlockFence and block.meta != null then
84 meta = block.meta.to_s
85 end
86 # Do not try to highlight non-nit code.
87 if meta != "nit" and meta != "nitish" then
88 v.add "<pre class=\"{meta}\"><code>"
89 v.emit_in block
90 v.add "</code></pre>\n"
91 return
92 end
93 # Try to parse code
94 var code = code_from_block(block)
95 var ast = toolcontext.parse_something(code)
96 if ast isa AError then
97 v.add "<pre class=\"{meta}\"><code>"
98 v.emit_in block
99 v.add "</code></pre>\n"
100 return
101 end
102 v.add "<pre class=\"nitcode\"><code>"
103 var hl = new HighlightVisitor
104 hl.line_id_prefix = ""
105 hl.enter_visit(ast)
106 v.add(hl.html)
107 v.add "</code></pre>\n"
108 end
109
110 redef fun add_span_code(v, text, from, to) do
111 # Try to parse it
112 var code = code_from_text(text, from, to)
113 var ast = toolcontext.parse_something(code)
114
115 if ast isa AError then
116 v.add "<code class=\"rawcode\">"
117 append_code(v, text, from, to)
118 else
119 v.add "<code class=\"nitcode\">"
120 var hl = new HighlightVisitor
121 hl.line_id_prefix = ""
122 hl.enter_visit(ast)
123 v.add(hl.html)
124 end
125 v.add "</code>"
126 end
127
128 fun code_from_text(buffer: Text, from, to: Int): String do
129 var out = new FlatBuffer
130 for i in [from..to[ do out.add buffer[i]
131 return out.write_to_string
132 end
133
134 fun code_from_block(block: BlockCode): String do
135 var infence = block isa BlockFence
136 var text = new FlatBuffer
137 var line = block.block.first_line
138 while line != null do
139 if not line.is_empty then
140 var str = line.value
141 if not infence and str.has_prefix(" ") then
142 text.append str.substring(4, str.length - line.trailing)
143 else
144 text.append str
145 end
146 end
147 text.append "\n"
148 line = line.next
149 end
150 return text.write_to_string
151 end
152 end
153
154 # Decorator for span elements.
155 #
156 # Because inline comments can appear as span elements,
157 # InlineDecorator do not decorate things like paragraphs or headers.
158 private class InlineDecorator
159 super NitdocDecorator
160
161 redef fun add_paragraph(v, block) do
162 v.emit_in block
163 end
164
165 redef fun add_headline(v, block) do
166 v.emit_in block
167 end
168
169 redef fun add_code(v, block) do
170 # Try to parse code
171 var ast = toolcontext.parse_something(block.block.text.to_s)
172 if ast isa AError then
173 v.add "<code>"
174 v.emit_in block
175 v.add "</code>"
176 return
177 end
178 v.add "<code class=\"nitcode\">"
179 var hl = new HighlightVisitor
180 hl.enter_visit(ast)
181 v.add(hl.html)
182 v.add "</code>"
183 end
184 end
185
186 redef class Model
187 # Get a markdown processor for Nitdoc comments.
188 private var nitdoc_md_processor: MarkdownProcessor is lazy do
189 var proc = new MarkdownProcessor
190 proc.emitter.decorator = new NitdocDecorator
191 return proc
192 end
193
194 # Get a markdown inline processor for Nitdoc comments.
195 #
196 # This processor is specificaly designed to inlinable doc elements like synopsys.
197 private var nitdoc_inline_processor: MarkdownProcessor is lazy do
198 var proc = new MarkdownProcessor
199 proc.emitter.decorator = new InlineDecorator
200 return proc
201 end
202 end