e00a02486e8b6fdbb388c96fa6e0634503140a0d
[nit.git] / src / doc / commands / commands_html.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Render commands results as HTML
16 module commands_html
17
18 import commands_catalog
19 import commands_graph
20 import commands_ini
21 import commands_main
22 import commands_parser
23 import commands_usage
24
25 import templates::templates_html
26 intrude import markdown::wikilinks
27
28 redef class DocCommand
29
30 # Render results as a HTML string
31 fun to_html: Writable do return "<p class='text-danger'>Not yet implemented</p>"
32 end
33
34 redef class CmdMessage
35
36 # Render the message as a HTML string
37 fun to_html: Writable is abstract
38 end
39
40 redef class CmdError
41 redef fun to_html do return "<p class='text-danger'>Error: {to_s}</p>"
42 end
43
44 redef class CmdWarning
45 redef fun to_html do return "<p class='text-warning'>Warning: {to_s}</p>"
46 end
47
48 # Model commands
49
50 redef class CmdEntity
51 redef fun to_html do
52 var mentity = self.mentity
53 if mentity == null then return ""
54 return mentity.html_link.write_to_string
55 end
56 end
57
58 redef class CmdEntities
59 redef fun to_html do
60 var mentities = self.results
61 if mentities == null then return ""
62
63 var tpl = new Template
64 tpl.add "<ul>"
65 for mentity in mentities do
66 var mdoc = mentity.mdoc_or_fallback
67 tpl.add "<li>"
68 tpl.add mentity.html_link
69 if mdoc != null then
70 tpl.add " - "
71 tpl.add mdoc.html_synopsis
72 end
73 tpl.add "</li>"
74 end
75 tpl.add "</ul>"
76 return tpl.write_to_string
77 end
78 end
79
80 redef class CmdComment
81 redef fun to_html do
82 var mentity = self.mentity
83 if mentity == null then return ""
84
85 var mdoc = self.mdoc
86 var tpl = new Template
87 tpl.add "<h3>"
88 # FIXME comments left here until I figure out what to do about the presentation options
89 # if not opts.has_key("no-link") then
90 tpl.add mentity.html_link
91 # end
92 if mdoc != null then
93 # if not opts.has_key("no-link") and not opts.has_key("no-synopsis") then
94 tpl.add " - "
95 # end
96 # if not opts.has_key("no-synopsis") then
97 tpl.add mdoc.html_synopsis
98 # end
99 end
100 tpl.add "</h3>"
101 if mdoc != null then
102 # if not opts.has_key("no-comment") then
103 tpl.add mdoc.html_comment
104 # end
105 end
106 return tpl.write_to_string
107 end
108
109 redef fun render_comment do
110 var mdoc = self.mdoc
111 if mdoc == null then return null
112
113 if format == "html" then
114 if full_doc then return mdoc.html_documentation
115 return mdoc.html_synopsis
116 end
117 return super
118 end
119 end
120
121 redef class CmdEntityLink
122 redef fun to_html do
123 var mentity = self.mentity
124 if mentity == null then return ""
125 return mentity.html_link(text, title).write_to_string
126 end
127 end
128
129 redef class CmdCode
130 redef fun to_html do
131 var node = self.node
132 if node == null then return ""
133
134 var code = render_code(node)
135 return "<pre>{code.write_to_string}</pre>"
136 end
137
138 redef fun render_code(node) do
139 if format == "html" then
140 var hl = new CmdHtmlightVisitor
141 hl.show_infobox = false
142 hl.highlight_node node
143 return hl.html
144 end
145 return super
146 end
147 end
148
149 # Custom HtmlightVisitor for commands
150 #
151 # We create a new subclass so its behavior can be refined in clients without
152 # breaking the main implementation.
153 class CmdHtmlightVisitor
154 super HtmlightVisitor
155
156 redef fun hrefto(mentity) do
157 if mentity isa MClassDef then return mentity.mclass.html_url
158 if mentity isa MPropDef then return mentity.mproperty.html_url
159 return mentity.html_url
160 end
161 end
162
163 redef class CmdAncestors
164 redef fun to_html do return super # FIXME lin
165 end
166
167 redef class CmdParents
168 redef fun to_html do return super # FIXME lin
169 end
170
171 redef class CmdChildren
172 redef fun to_html do return super # FIXME lin
173 end
174
175 redef class CmdDescendants
176 redef fun to_html do return super # FIXME lin
177 end
178
179 redef class CmdFeatures
180 redef fun to_html do return super # FIXME lin
181 end
182
183 redef class CmdLinearization
184 redef fun to_html do return super # FIXME lin
185 end
186
187 # Usage commands
188
189 redef class CmdNew
190 redef fun to_html do return super # FIXME lin
191 end
192
193 redef class CmdCall
194 redef fun to_html do return super # FIXME lin
195 end
196
197 redef class CmdReturn
198 redef fun to_html do return super # FIXME lin
199 end
200
201 redef class CmdParam
202 redef fun to_html do return super # FIXME lin
203 end
204
205 # Graph commands
206
207 redef class CmdGraph
208 redef fun to_html do
209 var output = render
210 if output == null then return ""
211 return output.write_to_string
212 end
213 end
214
215 # Ini commands
216
217 redef class CmdIniDescription
218 redef fun to_html do
219 var desc = self.desc
220 if desc == null then return ""
221
222 return "<p>{desc}</p>"
223 end
224 end
225
226 redef class CmdIniGitUrl
227 redef fun to_html do
228 var url = self.url
229 if url == null then return ""
230
231 return "<a href=\"{url}\">{url}</a>"
232 end
233 end
234
235 redef class CmdIniCloneCommand
236 redef fun to_html do
237 var command = self.command
238 if command == null then return ""
239
240 return "<pre>{command}</pre>"
241 end
242 end
243
244 redef class CmdIniIssuesUrl
245 redef fun to_html do
246 var url = self.url
247 if url == null then return ""
248
249 return "<a href=\"{url}\">{url}</a>"
250 end
251 end
252
253 redef class CmdIniMaintainer
254 redef fun to_html do
255 var name = self.maintainer
256 if name == null then return ""
257
258 return "<b>{name.html_escape}</b>"
259 end
260 end
261
262 redef class CmdIniContributors
263 redef fun to_html do
264 var names = self.contributors
265 if names == null or names.is_empty then return ""
266
267 var tpl = new Template
268 tpl.add "<ul>"
269 for name in names do
270 tpl.add "<li><b>{name.html_escape}</b></li>"
271 end
272 tpl.add "</ul>"
273 return tpl.write_to_string
274 end
275 end
276
277 redef class CmdIniLicense
278 redef fun to_html do
279 var license = self.license
280 if license == null then return ""
281
282 return "<a href=\"https://opensource.org/licenses/{license}\">{license}</a>"
283 end
284 end
285
286 redef class CmdEntityFile
287
288 # URL to the file
289 #
290 # Can be refined in subtools.
291 var file_url: nullable String = file is lazy, writable
292
293 redef fun to_html do
294 var file = self.file
295 if file == null then return ""
296
297 return "<a href=\"{file_url or else ""}\">{file.basename}</a>"
298 end
299 end
300
301 redef class CmdEntityFileContent
302 redef fun to_html do
303 var content = self.content
304 if content == null then return ""
305
306 return "<pre>{content}</pre>"
307 end
308 end
309
310 # Main commands
311
312 redef class CmdMains
313 redef fun to_html do return super # FIXME lin
314 end
315
316 redef class CmdMainCompile
317 redef fun to_html do
318 var command = self.command
319 if command == null then return ""
320
321 return "<pre>{command}</pre>"
322 end
323 end
324
325 redef class CmdManSynopsis
326 redef fun to_html do
327 var synopsis = self.synopsis
328 if synopsis == null then return ""
329
330 return "<pre>{synopsis}</pre>"
331 end
332 end
333
334 redef class CmdManOptions
335 redef fun to_html do
336 var options = self.options
337 if options == null or options.is_empty then return ""
338
339 var tpl = new Template
340 tpl.addn "<pre>"
341 tpl.addn "<table width='100%'>"
342 for opt, desc in options do
343 tpl.addn "<tr>"
344 tpl.addn "<th valign='top' width='30%'>{opt}</th>"
345 tpl.addn "<td width='70%'>{desc}</td>"
346 tpl.addn "</tr>"
347 end
348 tpl.addn "</table>"
349 tpl.addn "</pre>"
350
351 return tpl.write_to_string
352 end
353 end
354
355 redef class CmdTesting
356 redef fun to_html do
357 var command = self.command
358 if command == null then return ""
359
360 return "<pre>{command}</pre>"
361 end
362 end
363
364 # MDoc
365
366 # Custom Markdown processor able to process doc commands
367 class CmdDecorator
368 super NitdocDecorator
369
370 redef type PROCESSOR: CmdMarkdownProcessor
371
372 # Model used by wikilink commands to find entities
373 var model: Model
374
375 # Filter to apply if any
376 var filter: nullable ModelFilter
377
378 redef fun add_span_code(v, buffer, from, to) do
379 var text = new FlatBuffer
380 buffer.read(text, from, to)
381 var name = text.write_to_string
382 name = name.replace("nullable ", "")
383 var mentity = try_find_mentity(name)
384 if mentity == null then
385 super
386 else
387 v.add "<code>"
388 v.emit_text mentity.html_link.write_to_string
389 v.add "</code>"
390 end
391 end
392
393 private fun try_find_mentity(text: String): nullable MEntity do
394 var mentity = model.mentity_by_full_name(text, filter)
395 if mentity != null then return mentity
396
397 var mentities = model.mentities_by_name(text, filter)
398 if mentities.is_empty then
399 return null
400 else if mentities.length > 1 then
401 # TODO smart resolve conflicts
402 end
403 return mentities.first
404 end
405
406 redef fun add_wikilink(v, token) do
407 v.render_wikilink(token, model)
408 end
409 end
410
411 # Same as `InlineDecorator` but with wikilink commands handling
412 class CmdInlineDecorator
413 super InlineDecorator
414
415 redef type PROCESSOR: CmdMarkdownProcessor
416
417 # Model used by wikilink commands to find entities
418 var model: Model
419
420 redef fun add_wikilink(v, token) do
421 v.render_wikilink(token, model)
422 end
423 end
424
425 # Custom MarkdownEmitter for commands
426 class CmdMarkdownProcessor
427 super MarkdownProcessor
428
429 # Parser used to process doc commands
430 var parser: CommandParser
431
432 # Render a wikilink
433 fun render_wikilink(token: TokenWikiLink, model: Model) do
434 var link = token.link
435 if link == null then return
436 var name = token.name
437 if name != null then link = "{name} | {link}"
438
439 var command = parser.parse(link.write_to_string)
440 var error = parser.error
441
442 if error isa CmdError then
443 emit_text error.to_html.write_to_string
444 return
445 end
446 if error isa CmdWarning then
447 emit_text error.to_html.write_to_string
448 end
449 add command.as(not null).to_html
450 end
451 end
452
453 redef class Text
454 # Read `self` between `nstart` and `nend` (excluded) and writte chars to `out`.
455 private fun read(out: FlatBuffer, nstart, nend: Int): Int do
456 var pos = nstart
457 while pos < length and pos < nend do
458 out.add self[pos]
459 pos += 1
460 end
461 if pos == length then return -1
462 return pos
463 end
464 end