1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Nitdoc specific Markdown format handling for Nitweb
19 intrude import doc_down
20 intrude import markdown
::wikilinks
23 # Docdown handler accept docdown as POST data and render it as HTML
27 # Modelbuilder used by the commands
28 var modelbuilder
: ModelBuilder
30 # Specific Markdown processor to use within Nitweb
31 var md_processor
: MarkdownProcessor is lazy
do
32 var proc
= new MarkdownProcessor
33 proc
.emitter
.decorator
= new NitwebDecorator(view
, modelbuilder
)
37 redef fun post
(req
, res
) do
38 res
.html md_processor
.process
(req
.body
)
42 # Specific Markdown decorator for Nitweb
44 # We reuse all the implementation of the NitdocDecorator and add the wikilinks handling.
48 # View used by wikilink commands to find model entities
51 # Modelbuilder used to access code
52 var modelbuilder
: ModelBuilder
54 redef fun add_wikilink
(v
, token
) do
56 if link
== null then return
57 var cmd
= new DocCommand(link
.write_to_string
)
58 cmd
.render
(v
, token
, view
)
62 # Same as `InlineDecorator` but with wikilink commands handling
63 class NitwebInlineDecorator
66 # View used by wikilink commands to find model entities
69 # Modelbuilder used to access code
70 var modelbuilder
: ModelBuilder
72 redef fun add_wikilink
(v
, token
) do
74 if link
== null then return
75 var cmd
= new DocCommand(link
.write_to_string
)
76 cmd
.render
(v
, token
, view
)
80 redef interface DocCommand
82 # Emit the HTML related to the execution of this doc command
83 fun render
(v
: MarkdownEmitter, token
: TokenWikiLink, model
: ModelView) do
84 write_error
(v
, "Not yet implemented command `{token.link or else "null"}`")
87 # Find the MEntity ` with `full_name`.
88 fun find_mentity
(model
: ModelView, full_name
: nullable String): nullable MEntity do
89 if full_name
== null then return null
90 return model
.mentity_by_full_name
(full_name
.from_percent_encoding
)
93 # Write a warning in the output
94 fun write_warning
(v
: MarkdownEmitter, text
: String) do
95 v
.emit_text
"<p class='text-warning'>Warning: {text}</p>"
98 # Write an error in the output
99 fun write_error
(v
: MarkdownEmitter, text
: String) do
100 v
.emit_text
"<p class='text-danger'>Error: {text}</p>"
103 # Write a link to a mentity in the output
104 fun write_mentity_link
(v
: MarkdownEmitter, mentity
: MEntity) do
105 var link
= mentity
.web_url
106 var name
= mentity
.name
107 var mdoc
= mentity
.mdoc_or_fallback
109 if mdoc
!= null then comment
= mdoc
.synopsis
110 v
.decorator
.add_link
(v
, link
, name
, comment
)
114 redef class UnknownCommand
115 redef fun render
(v
, token
, model
) do
116 var link
= token
.link
118 write_error
(v
, "Empty command")
121 var full_name
= link
.write_to_string
122 var mentity
= find_mentity
(model
, full_name
)
123 if mentity
== null then
124 write_error
(v
, "Unknown command `{link}`")
127 write_mentity_link
(v
, mentity
)
131 redef class ArticleCommand
132 redef fun render
(v
, token
, model
) do
133 if args
.is_empty
then
134 write_error
(v
, "Expected one arg: the MEntity name")
137 var name
= args
.first
138 var mentity
= find_mentity
(model
, name
)
139 if mentity
== null then
140 write_error
(v
, "No MEntity found for name `{name}`")
143 var mdoc
= mentity
.mdoc_or_fallback
145 write_warning
(v
, "No MDoc for mentity `{name}`")
149 write_mentity_link
(v
, mentity
)
151 v
.emit_text mdoc
.synopsis
153 v
.add v
.processor
.process
(mdoc
.comment
).write_to_string
157 redef class CommentCommand
158 redef fun render
(v
, token
, model
) do
159 if args
.is_empty
then
160 write_error
(v
, "Expected one arg: the MEntity name")
163 var name
= args
.first
164 var mentity
= find_mentity
(model
, name
)
165 if mentity
== null then
166 write_error
(v
, "No MEntity found for name `{name}`")
169 var mdoc
= mentity
.mdoc_or_fallback
171 write_warning
(v
, "No MDoc for mentity `{name}`")
174 v
.add v
.processor
.process
(mdoc
.comment
).write_to_string
178 redef class ListCommand
179 redef fun render
(v
, token
, model
) do
180 if args
.is_empty
then
181 write_error
(v
, "Expected one arg: the MEntity name")
184 var name
= args
.first
185 var mentity
= find_mentity
(model
, name
)
186 if mentity
isa MPackage then
187 write_list
(v
, mentity
.mgroups
)
188 else if mentity
isa MGroup then
189 var res
= new Array[MEntity]
190 res
.add_all mentity
.in_nesting
.smallers
191 res
.add_all mentity
.mmodules
193 else if mentity
isa MModule then
194 write_list
(v
, mentity
.mclassdefs
)
195 else if mentity
isa MClass then
196 write_list
(v
, mentity
.collect_intro_mproperties
(model
))
197 else if mentity
isa MClassDef then
198 write_list
(v
, mentity
.mpropdefs
)
199 else if mentity
isa MProperty then
200 write_list
(v
, mentity
.mpropdefs
)
202 write_error
(v
, "No list found for name `{name}`")
206 # Write a mentity list in the output
207 fun write_list
(v
: MarkdownEmitter, mentities
: Collection[MEntity]) do
209 for mentity
in mentities
do
210 var mdoc
= mentity
.mdoc_or_fallback
212 write_mentity_link
(v
, mentity
)
215 v
.emit_text mdoc
.synopsis
223 redef class CodeCommand
224 redef fun render
(v
, token
, model
) do
225 if args
.is_empty
then
226 write_error
(v
, "Expected one arg: the MEntity name")
229 var name
= args
.first
230 var mentity
= find_mentity
(model
, name
)
231 if mentity
== null then
232 write_error
(v
, "No MEntity found for name `{name}`")
235 if mentity
isa MClass then mentity
= mentity
.intro
236 if mentity
isa MProperty then mentity
= mentity
.intro
237 var source
= render_source
(mentity
, v
.decorator
.as(NitwebDecorator).modelbuilder
)
238 if source
== null then
239 write_error
(v
, "No source for MEntity `{name}`")
247 # Highlight `mentity` source code.
248 private fun render_source
(mentity
: MEntity, modelbuilder
: ModelBuilder): nullable HTMLTag do
249 var node
= modelbuilder
.mentity2node
(mentity
)
250 if node
== null then return null
251 var hl
= new HighlightVisitor
257 redef class GraphCommand
258 redef fun render
(v
, token
, model
) do
259 if args
.is_empty
then
260 write_error
(v
, "Expected one arg: the MEntity name")
263 var name
= args
.first
264 var mentity
= find_mentity
(model
, name
)
265 if mentity
== null then
266 write_error
(v
, "No MEntity found for name `{name}`")
269 var g
= new InheritanceGraph(mentity
, model
)
270 v
.add g
.draw
(3, 3).to_svg