1 #=======================================================================
3 __version__
= '''0.0.01'''
4 __sub_version__
= '''20080311152519'''
5 __copyright__
= '''(c) Alex A. Naanou 2008'''
8 #-----------------------------------------------------------------------
10 import pli
.structdoc
.core
as core
12 from pli
.functional
import curry
16 #-----------------------------------------------------------------------
18 # XXX use templates and direct HTML representation for rendering...
19 # Tree ---(template)--> HTML --> file
20 # XXX clean things up...
23 #-----------------------------------------------------------------------
25 #-------------------------------------------------------NodeContainer---
26 class NodeContainer(core
.NodeContainer
):
29 def __init__(self
, *nodes
):
32 ##!!! this is not the best wat to go...
33 super(NodeContainer
, self
).__init
__()
39 i
= self
._get
_unique
_key
()
41 def _get_unique_key(self
):
44 key
= str(time
.time())
45 while key
in self
.keys():
46 key
= str(time
.time())
50 ##---------------------------------------------NodeContainerWithTitle---
51 class NodeContainerWithTitle(NodeContainer
):
54 def __init__(self
, title
, *nodes
):
57 super(NodeContainerWithTitle
, self
).__init
__(*nodes
)
61 #-----------------------------------------------------------------------
62 #----------------------------------------------------------------Site---
63 class Site(NodeContainerWithTitle
):
65 can contain any number of nodes.
70 #----------------------------------------------------------------Page---
71 class Page(NodeContainerWithTitle
):
73 can contain any number of nodes.
78 #-------------------------------------------------------------Section---
79 class Section(NodeContainerWithTitle
):
81 can contain any number of nodes.
86 #----------------------------------------------------------------Text---
87 class Text(NodeContainer
):
93 #---------------------------------------------------------------Group---
94 class Group(NodeContainer
):
100 #----------------------------------------------------------------Link---
101 class Link(NodeContainer
):
105 - any node (usually a container)
107 def __init__(self
, title
, obj
):
110 super(Link
, self
).__init
__()
111 self
['title'] = title
116 #-----------------------------------------------------------------------
122 # - html (edit) -- combined with view
125 # * might be a good idea to implement the render as a template...
126 #------------------------------------------------------BaseRSTContext---
127 class BaseRSTContext(core
.NodeContext
):
135 return self
._rst
_node
(1, self
._node
, cache
=set())
137 def _rst_str(self
, node
, cache
=None):
141 def _rst_unknown(self
, level
, node
, cache
=None):
144 return '\n' + ' '*(level
-1) + '''%(node_name)s %(title)s:\n%(content)s'''\
146 title
=repr(node
.get('title', '')),
147 node_name
=node
.__class
__.__name
__,
148 content
=('\n' + ' '*(level
-1)).join([self
._rst
_node
(level
+1, node
[n
], cache
=cache
) \
149 for n
in node
.keys() \
150 if n
!= 'title' ])) + '\n'
151 def _rst_node(self
, level
, node
, cache
=None):
162 return self
._rst
_node
(level
, Text(Link(t
, node
)), cache
)
166 if t
in (str, unicode):
167 return self
._rst
_str
(node
, cache
=cache
)
168 return self
._rst
_unknown
(level
, node
, cache
=cache
)
171 #----------------------------------------------------------RSTContext---
172 # XXX write a node generator (rst-tree)
173 # XXX needs a selector...
174 ##class RSTContext(core.NodeContext):
175 class RSTContext(BaseRSTContext
):
179 def _rst_page(self
, node
, cache
=None):
182 return '''%(title)s\n----\n%(content)s'''\
185 content
='\n'.join([self
._rst
_node
(1, node
[n
], cache
=cache
) \
186 for n
in node
.keys() \
188 def _rst_section(self
, level
, node
, cache
=None):
191 return '\n' + ' '*(level
-1) + '''%(q)s %(title)s %(q)s\n%(content)s'''\
195 content
=('\n' + ' '*(level
-1)).join([self
._rst
_node
(level
+1, node
[n
], cache
=cache
) \
196 for n
in node
.keys() \
197 if n
!= 'title'])) + '\n'
198 def _rst_text(self
, level
, node
, cache
=None):
201 ## return '\n' + ' '.join([ self._rst_node(level, node[n]) \
202 return '\n' + ' '*(level
-1) + ' '.join([ self
._rst
_node
(level
, node
[n
], cache
=cache
) \
203 for n
in node
.keys() ])
204 def _rst_link(self
, node
, cache
=None):
207 return '[[%(title)s|%(url)s|%(alt)s]]' \
212 ##!!! make this extend BaseRSTContext._rst_node...
213 def _rst_node(self
, level
, node
, cache
=None):
224 return self
._rst
_node
(level
, Text(Link(t
, node
)), cache
)
229 return self
._rst
_page
(node
, cache
=cache
)
232 return self
._rst
_link
(node
, cache
=cache
)
235 return self
._rst
_section
(level
, node
, cache
=cache
)
238 return self
._rst
_text
(level
, node
, cache
=cache
)
240 elif t
in (str, unicode):
241 return self
._rst
_str
(node
, cache
=cache
)
242 return self
._rst
_unknown
(level
, node
, cache
=cache
)
244 # XXX node generator.... (rst input...)
248 #---------------------------------------------------------HTMLContext---
249 # NOTE: this will not create pretty HTML, it was not the goal...
250 # XXX this does not consider titles as nodes... (wrong?)
251 class HTMLContext(core
.NodeContext
):
255 # XXX move these to files...
265 ##!!! this is wrong.... should dynamicly figure this out...
266 _template_dir
= './templates/plain/'
269 # XXX move this to someplace more generic...
273 return self
.html_tpl \
276 content
=self
._html
_node
(self
, 1, self
._node
, cache
=cache
))
277 # XXX make this the default...
284 node
= self
._get
_page
()
285 return self
.html_tpl \
287 title
=self
._node
['title'],
288 content
=node
._html
_page
(self
, 1, node
._node
, self
._node
, cache
=cache
))
289 ##!!! STUB -- need to create a real relative or server absolute URL... (will depend on server)
290 # XXX need to find the shortest path form node to root or to
291 # current page (site-absolute or relative).
293 def url(self
, target
=None):
296 NOTE: if target is omited then return url to self.
299 return '/' + '/'.join(self
.path
)
301 raise NotImplementedError
304 def __init__(self
, *p
, **n
):
307 super(HTMLContext
, self
).__init
__(*p
, **n
)
308 self
._reload
_templates
()
313 get the nearest page up in the context...
317 while node
.type != 'Page':
320 def _reload_templates(self
):
323 for tpl
in self
._templates
:
324 setattr(self
, tpl
+ '_tpl', file('%s/%s.tpl' % (self
._template
_dir
, tpl
), 'r').read())
326 def _html_page(self
, context
, level
, page
, emphasize
=None, cache
=None):
329 return self
.page_tpl \
332 content
=''.join([ self
._html
_node
(context
, level
, page
[n
], emphasize
=emphasize
, cache
=cache
) \
333 for n
in page
.keys() \
335 def _html_emphasized(self
, context
, level
, node
, cache
=None):
339 return self
.emphasized_tpl \
341 content
=self
._html
_node
(context
, level
, node
, cache
=cache
))
342 def _html_section(self
, context
, level
, section
, emphasize
, cache
=None):
344 raise ValueError, 'html sections do not support nesting level greater than 6 (got %s)' % level
345 return self
.section_tpl \
348 title
=section
['title'],
349 content
=''.join([ self
._html
_node
(context
, level
+1, section
[n
], emphasize
, cache
=cache
) \
350 for n
in section
.keys() \
352 def _html_text(self
, context
, level
, node
, cache
=None):
355 return self
.text_tpl \
356 % ' '.join([ self
._html
_node
(context
, level
+1, node
[n
], cache
=cache
) for n
in node
.keys() ])
357 def _html_str(self
, context
, node
, cache
=None):
361 # XXX need to get the referenced object via the context...
362 def _html_link(self
, context
, node
, cache
=None):
365 return self
.link_tpl \
371 def _html_unknown(self
, context
, level
, node
, emphasize
, cache
=None):
374 return self
.unknown_tpl \
377 node_name
=node
.__class
__.__name
__,
378 content
=''.join([ self
._html
_node
(context
, level
, node
[n
],
379 emphasize
=emphasize
, cache
=cache
) \
380 for n
in node
.keys() ]))
381 def _html_node(self
, context
, level
, node
, emphasize
=None, cache
=None):
390 return self
._html
_node
(context
, level
, Text(Link(t
, node
)), emphasize
, cache
)
394 if node
== emphasize
:
395 return self
._html
_emphasized
(context
, level
, node
, cache
=cache
)
397 return self
._html
_link
(context
, node
, cache
=cache
)
400 return self
._html
_section
(context
, level
, node
, emphasize
, cache
=cache
)
403 return self
._html
_section
(context
, level
, node
, emphasize
, cache
=cache
)
406 return self
._html
_text
(context
, level
, node
, cache
=cache
)
408 elif t
in (str, unicode):
409 return self
._html
_str
(context
, node
, cache
=cache
)
410 return self
._html
_unknown
(context
, level
, node
, emphasize
, cache
=cache
)
413 #---------------------------------------------------RawRSTHTMLContext---
414 class RawRSTHTMLContext(HTMLContext
, BaseRSTContext
):
420 #------------------------------------------------------RSTHTMLContext---
421 class RSTHTMLContext(HTMLContext
, RSTContext
):
428 #-----------------------------------------------------------------------
429 if __name__
== '__main__':
431 from test_page
import root
433 # render and save by path...
434 def render(path
, format
='html', ext
=None):
436 path
= path
.split('/')
445 # render and save to file....
446 file('./test/%s.%s' % (cur
.name
, ext
), 'w').write(getattr(cur
, format
))
450 render('/p/first section/')
451 render('p/first section/', format
='rawhtml', ext
='raw.html')
452 render('p/first section/nested section/')
453 render('p/first section/nested section/another nested section')
455 render('/p', format
='rst')
456 render('/p/first section/', format
='rst')
457 render('p/first section/nested section/', format
='rst')
463 #=======================================================================|# vim:set ts=4 sw=4 nowrap :