1 """
2 mopowg
3 ======
4
5 mopowg is an easy to install, cross-platform doc generator which is based on docutils.
6
7 mopowg could generate full documents with figures, styles, and syntax highlighting blocks.
8
9 fredlin 2007, gasolin+mopowg@gmail.com
10
11 - Scanner
12 - Generator
13 - Convertor
14 - Formater
15 - high_lighter
16 - Processor
17 - Templater (genshi)
18 - Saver
19 - css_writer
20
21 ----
22
23 doc processing
24 --------------
25
26 Diagram::
27
28 ___________
29 | |
30 | files |
31 | |
32 \|_________|/
33 \ /
34 Scanner -> file_list
35 |||
36 Generator - Formater -> contents
37 |||
38 Processor -> files (content, presentation)
39 \|/
40 ___________
41 | |
42 | docs |
43 | |
44 |_________|
45
46 ----
47
48 doc hosting[1]
49 --------------
50
51 Runner is the build in server which host the documents;
52
53 Plugins:
54
55 Interpreter is the crunchy interpreter that allow you to execute the demo codes on doc;
56
57 Commenter is append fields for comment
58
59 Diagram::
60
61 ___________
62 | |
63 | files |
64 | |
65 |_________|
66 |
67 ----------------
68 |doc processing|
69 ----------------
70 |
71 Runner - plugins
72 |
73 |- Interpreter
74 |
75 |_ Commenter
76
77 ----
78
79 doc collaborative [1]
80 ---------------------
81
82 Diagram::
83
84 ___________
85 | |
86 | files |--hg repository
87 | |
88 |_________|
89 |
90 ----------------
91 |doc processing|
92 ----------------
93 |
94 ----------------
95 | doc hosting |
96 ----------------
97 |
98 wikier
99
100 ----
101
102 [1]: not implemented yet
103
104 ----
105
106 This is the MIT license:
107 http://www.opensource.org/licenses/mit-license.php
108
109 Copyright (c) 2007 Fred Lin and contributors. Mopowg is a trademark of Fred Lin.
110
111 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
112
113 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
114
115 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
116 """
117 import os
118
119 -def proc_dir(file_list, dirName, files):
120 """
121 The callback function of os.path.walk() to get the list of scanned
122 files.
123 """
124 for i in files:
125 fn = os.path.join(dirName, i)
126 if os.path.isdir(fn):
127 continue
128 elif os.path.isfile(fn):
129 file_list.append(fn)
130
132 """scan a folder
133
134 scanner is a preprocess class to collect files
135
136 scanner currently allow single layer only
137 """
138 if path:
139 if os.path.isdir(path):
140
141
142 pass
143 else:
144 path = os.path.join(os.getcwd,path)
145 else:
146 path = os.getcwd()
147
148 file_list = []
149 os.path.walk(path, proc_dir, file_list)
150 return file_list
151
152
153 default_style="""body {
154 margin: 0;
155 padding: 0;
156 font-family: Verdana, "Lucida Grande", sans-serif;
157 text-align: left;
158 /*text-align: center;*/
159 line-height: 1.3em;
160 color: #333;
161 background: #fff;
162 padding: 20px 20px 0 20px;
163 }
164 .literal-block { background: #fff0f0; border: solid 1px #ccc;
165 padding:2px 2px 2px 10px; margin: 5px 5px 5px 5px; line-height:1.2em; } /* Block */
166 .note { background: #f0ff00; border: solid 1px #ccc;
167 padding:2px 2px 2px 10px; margin: 5px 5px 5px 5px; line-height:1.2em; } /* Notes */
168 .highlight { background: #f0f0f0; border: solid 1px #ccc;
169 padding:2px 2px 2px 10px; margin: 5px 5px 5px 5px; line-height:1.2em; }
170 .highlight .c { color: #60a0b0; font-style: italic } /* Comment */
171 .highlight .err { border: 1px solid #FF0000 } /* Error */
172 .highlight .k { color: #007020; font-weight: bold } /* Keyword */
173 .highlight .o { color: #666666 } /* Operator */
174 .highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
175 .highlight .cp { color: #007020 } /* Comment.Preproc */
176 .highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
177 .highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
178 .highlight .gd { color: #A00000 } /* Generic.Deleted */
179 .highlight .ge { font-style: italic } /* Generic.Emph */
180 .highlight .gr { color: #FF0000 } /* Generic.Error */
181 .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
182 .highlight .gi { color: #00A000 } /* Generic.Inserted */
183 .highlight .go { color: #808080 } /* Generic.Output */
184 .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
185 .highlight .gs { font-weight: bold } /* Generic.Strong */
186 .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
187 .highlight .gt { color: #0040D0 } /* Generic.Traceback */
188 .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
189 .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
190 .highlight .kp { color: #007020 } /* Keyword.Pseudo */
191 .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
192 .highlight .kt { color: #007020; font-weight: bold } /* Keyword.Type */
193 .highlight .m { color: #40a070 } /* Literal.Number */
194 .highlight .s { color: #4070a0 } /* Literal.String */
195 .highlight .na { color: #4070a0 } /* Name.Attribute */
196 .highlight .nb { color: #007020 } /* Name.Builtin */
197 .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
198 .highlight .no { color: #60add5 } /* Name.Constant */
199 .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
200 .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
201 .highlight .ne { color: #007020 } /* Name.Exception */
202 .highlight .nf { color: #06287e } /* Name.Function */
203 .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
204 .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
205 .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
206 .highlight .nv { color: #bb60d5 } /* Name.Variable */
207 .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
208 .highlight .mf { color: #40a070 } /* Literal.Number.Float */
209 .highlight .mh { color: #40a070 } /* Literal.Number.Hex */
210 .highlight .mi { color: #40a070 } /* Literal.Number.Integer */
211 .highlight .mo { color: #40a070 } /* Literal.Number.Oct */
212 .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
213 .highlight .sc { color: #4070a0 } /* Literal.String.Char */
214 .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
215 .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
216 .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
217 .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
218 .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
219 .highlight .sx { color: #c65d09 } /* Literal.String.Other */
220 .highlight .sr { color: #235388 } /* Literal.String.Regex */
221 .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
222 .highlight .ss { color: #517918 } /* Literal.String.Symbol */
223 .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
224 .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
225 .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
226 .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
227 .highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */
228 """
229
230 -def css_writer(output, style, filename='style.css'):
231 """write css
232
233 output:
234 output path
235 style:
236 custom style string
237 filename:
238 output filename
239 """
240 outpath = os.path.join(output,filename)
241 if not os.path.exists(outpath):
242 print 'saved to %s'%outpath
243 fd = file(outpath, 'w')
244 fd.write(style)
245 fd.close()
246
247 -def saver(path, content, output, style='', nostyle=False, ext='.html'):
248 """save content to file
249
250 output: dir
251
252 saver is the processor which is used to store contents to actual files;
253
254 nostyle:
255 not generate the css style
256 ext:
257 the file extension. default value is '.html'.
258 """
259 filename = os.path.splitext(os.path.split(path)[1])[0]+ext
260
261 if not output:
262 output = os.path.split(path)[0]
263
264 if not os.path.exists(output):
265 os.mkdir(output)
266
267 sav = os.path.join(output, filename)
268 print "saved to %s"%sav
269 fd = file(sav, 'w')
270 fd.write(content)
271 fd.close()
272
273 if (os.path.exists(os.path.join(path,style)) or os.path.exists(style)):
274 fd = file(style, 'r')
275 style = fd.read()
276 fd.close()
277
278 if not nostyle:
279 css_writer(output, style)
280
281
282
283 default_template = """
284 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
285 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
286 <html xmlns="http://www.w3.org/1999/xhtml"
287 xmlns:py="http://genshi.edgewall.org/"
288 xmlns:xi="http://www.w3.org/2001/XInclude">
289 <head>
290 <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
291 <title>Doc generated by mopowg</title>
292 <link rel="stylesheet" type="text/css" media="screen" href="style.css" />
293 </head>
294 <body>
295 <div id="content" py:content="Markup(content)">
296 hello world
297 </div>
298 </body>
299 </html>
300 """
301
303 """
304 generate with genshi template
305 """
306 from genshi.template import MarkupTemplate
307
308 if (os.path.exists(os.path.join(input,template)) or os.path.exists(template)):
309 fd = file(style, 'r')
310 template = fd.read()
311 fd.close()
312
313 tmpl = MarkupTemplate(template)
314 stream = tmpl.generate(content=content)
315 data = stream.render('html')
316 return data
317
318 -def processor(input, content, output, template, style, preview=False):
319 """process the content
320 """
321 content = templater(input, content, template)
322 if not preview:
323 saver(input, content, output, style)
324 else:
325 return content
326
327
328
329 from docutils import nodes
330 from docutils.parsers.rst import directives
331 from pygments import highlight
332 from pygments.lexers import get_lexer_by_name
333 from pygments.formatters import HtmlFormatter
334
335 -def pygments_directive(name, arguments, options, content, lineno,
336 content_offset, block_text, state, state_machine):
337 """register the docutils highlight function"""
338 try:
339 lexer = get_lexer_by_name(arguments[0])
340 except ValueError:
341
342 lexer = get_lexer_by_name('text')
343
344 formater = HtmlFormatter()
345 parsed = highlight(u'\n'.join(content), lexer, formater)
346 return [nodes.raw('', parsed, format='html')]
347 pygments_directive.arguments = (1, 0, 1)
348 pygments_directive.content = 1
349 directives.register_directive('code', pygments_directive)
350
351
352 import re
353
354 wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
355
357 """
358 Convert file to target format, include syntax highlight function
359
360 input: path
361 output: content
362
363 support features:
364 rich(rich content), wikiword, wikipattern
365 """
366 try:
367 from docutils.core import publish_parts
368 import pygments
369
370
371 except ImportError, e:
372 print e
373
374 fd = file(path, 'r')
375 data = fd.read()
376 fd.close()
377
378 if kw.get('rich', False):
379
380 content = publish_parts(data,writer_name="html")['html_body']
381 if kw.get('wikiword', False):
382
383 pattern = kw.get('wikipattern', r'<a href="\1.html">\1</a>')
384 print 'pattern: %s'%pattern
385 content = wikiwords.sub(pattern, content)
386 else:
387 content = data
388
389 return content
390
394 """generate docs
395
396 generator is used to generate docs;
397 """
398 for i in input:
399 if os.path.isfile(i) and os.path.splitext(i)[-1] in filter:
400
401 content = convertor(path=i, rich=rich, wikiword=wikiword)
402 processor(i, content, output, template, style, preview)
403
440
441
442
443
444
445
446 __all__ = ['scanner', 'processor', 'default_style', 'default_template',
447 'generator', 'convertor', 'css_writer']
448
449 if __name__=="__main__":
450
451 cmdtool()
452