From 405944827ca6858c04a66eef8cf4c5ca5df24620 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 13 Mar 2008 14:39:39 +0300 Subject: [PATCH] added pli.structdoc experimental module for reference and as a starting point. --- pli-structdoc/__init__.py | 11 + pli-structdoc/core.py | 421 ++++++++++++++++++++++++ pli-structdoc/structure.py | 463 +++++++++++++++++++++++++++ pli-structdoc/templates/plain/emphasized.tpl | 1 + pli-structdoc/templates/plain/general.css | 22 ++ pli-structdoc/templates/plain/html.tpl | 9 + pli-structdoc/templates/plain/link.tpl | 1 + pli-structdoc/templates/plain/page.tpl | 2 + pli-structdoc/templates/plain/section.tpl | 4 + pli-structdoc/templates/plain/text.tpl | 1 + pli-structdoc/templates/plain/unknown.tpl | 1 + pli-structdoc/test/general.css | 25 ++ pli-structdoc/test_page.py | 46 +++ pli-structdoc/test_srv.py | 56 ++++ 14 files changed, 1063 insertions(+) create mode 100755 pli-structdoc/__init__.py create mode 100755 pli-structdoc/core.py create mode 100755 pli-structdoc/structure.py create mode 100755 pli-structdoc/templates/plain/emphasized.tpl create mode 100755 pli-structdoc/templates/plain/general.css create mode 100755 pli-structdoc/templates/plain/html.tpl create mode 100755 pli-structdoc/templates/plain/link.tpl create mode 100755 pli-structdoc/templates/plain/page.tpl create mode 100755 pli-structdoc/templates/plain/section.tpl create mode 100755 pli-structdoc/templates/plain/text.tpl create mode 100755 pli-structdoc/templates/plain/unknown.tpl create mode 100755 pli-structdoc/test/general.css create mode 100755 pli-structdoc/test_page.py create mode 100755 pli-structdoc/test_srv.py diff --git a/pli-structdoc/__init__.py b/pli-structdoc/__init__.py new file mode 100755 index 0000000..e4a932b --- /dev/null +++ b/pli-structdoc/__init__.py @@ -0,0 +1,11 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20080121200707''' +__copyright__ = '''(c) Alex A. Naanou 2008''' + + +#----------------------------------------------------------------------- + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/pli-structdoc/core.py b/pli-structdoc/core.py new file mode 100755 index 0000000..c70b9e4 --- /dev/null +++ b/pli-structdoc/core.py @@ -0,0 +1,421 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20080307022726''' +__copyright__ = '''(c) Alex A. Naanou 2008''' + + +#----------------------------------------------------------------------- + +import pli.pattern.mixin.mapping as mapping +import pli.pattern.proxy.utils as putils + + +#----------------------------------------------------------------------- +# target general features: +# - node must be referencable from several places with proper context +# handling from each location (no explicit references or +# inclusions). +# - ability to reference any node in the graph (node path). +# - context referencing. +# - root refernecing +# - templating: +# - live template updates to influence all usage (update +# template, keep the slots). +# - template expansion. +# - editing: +# more specific features: +# - node type library. +# - template library. +# - render/editor backends: +# - html +# - wx +# - text/curses +# - ... +# +# basic node types: +# - container node +# - atomic node +# - text +# +#----------------------------------------------------------------------- +#--------------------------------------------------------AbstractNode--- +class AbstractNode(object): + ''' + ''' + pass + + +#-----------------------------------------------AbstractNodeContainer--- +class AbstractNodeContainer(AbstractNode): + ''' + ''' + pass + + +#-----------------------------------------------------AbstractContext--- +class AbstractContext(object): + ''' + ''' + pass + + + +#----------------------------------------------------------------------- +#----------------------------------------------------------------Node--- +class Node(AbstractNode): + ''' + ''' + pass + + +#-------------------------------------------------------NodeContainer--- +# must be something like a sorted mapping... +# XXX make this a generic mixin and move to an apropriate place... +class NodeContainer(AbstractNodeContainer, Node, mapping.Mapping): + ''' + ''' + _data = None + _order = None + def __init__(self): + ''' + ''' + self._data = {} + self._order = [] + def __getitem__(self, name): + ''' + ''' + data = self._data + if type(name) is slice: + # support the slice protocol... + start, stop, step = name.start, name.stop, name.step + # normalize the metric... + if start != None and type(start) not in (int, long): + start = self.index(start) + if stop != None and type(stop) not in (int, long): + stop = self.index(stop) + if step != None and type(step) not in (int, long): + raise TypeError, 'slice step bust be either an int or a long.' + # select the keys... + keys = self._order[slice(start, stop, step)] + # form the result... + return [ data[k] for k in keys ] + # normal key... + return data[name] + def __setitem__(self, name, value): + ''' + ''' + self._data[name] = value + if name not in self._order: + # by default add to the end... + self._order += [name] + def __delitem__(self, name): + ''' + ''' + del self._data[name] + self._order.remove(name) + def __iter__(self): + ''' + ''' + for n in self._order: + yield n + # list-like operations... + putils.proxymethods(( + 'index', + 'sort', + 'reverse'), + '_order') + # XXX anything more? + # specific methods... + def insertafter(self, key, nkey, value): + ''' + insert an item after key. + + NOTE: if nkey exists, then move the element. + ''' + i = self.index(key) + if nkey in self._order: + self._order.remove(nkey) + self._order.insert(i+1, nkey) + self._data[nkey] = value + def insertbefore(self, key, nkey, value): + ''' + ''' + i = self.index(key) + if nkey in self._order: + self._order.remove(nkey) + self._order.insert(i, nkey) + self._data[nkey] = value + def shift(self, offset, key): + ''' + move key up or down offset. + ''' + if offset == 0: + # nothing to do... + return + i = self._order.index(key) + del self._order[i] + if offset > 0: + offset -= 1 + self._order.insert(i+offset, key) + def keyat(self, index): + ''' + return key at position index. + ''' + return self._order[index] + def valueat(self, index): + ''' + return value at position index. + ''' + return self[self.keyat(index)] + def itemat(self, index): + ''' + return item at position index. + ''' + k = self.keyat(index) + return k, self[k] + + + +#---------------------------------------------------------NodeContext--- +# operations to support: +# browsing/selecting: +# parent +# next +# prev +# get/ +# editing: +# rename +# shift left/right +# move up/down +# remove +# new +# unwrap contents (move contennts up and remove container) +# wrap range +# clone +# move to (before/after/into) +# copy to +# +# XXX might be good to add more specific editor interface... +# XXX may be a good idea to make this into a mixin compatible with +# pli.pattern.proxy.InheritAndOverrideProxy... +class NodeContext(AbstractContext): + ''' + represents a specific path to a node. + + supports structural operations as well as node editing and conversion. + ''' + # basic internal data... + _parent = None + _key = None + _node = None + # introspection... + name = property( + doc='''\ + node name. this is the key in the container it was accessed from. + + on write, the new name will be cached in the context and will replace + the old key the object was accessed by. + ''', + fget=lambda self: self._key, + fset=lambda self, val: self.rename(val)) + # context navigation... + # XXX should this return a new context or reuse the old one?? + @property + def parent(self): + ''' + parent context. + ''' + return self._parent + @property + def next(self): + ''' + next context on the same level. + ''' + parent_node = self._parent._node + i = parent_node.index(self._key) + if i == len(parent_node) - 1: + ##!!! is this correct behaviour?? (return None or raise StopIteration) + raise IndexError, 'at last element.' + return self.__create_context__(self._parent, *parent_node.itemat(i+1)) + @property + def prev(self): + ''' + previous context on the same level. + ''' + parent_node = self._parent._node + i = parent_node.index(self._key) + if i == 0: + ##!!! is this correct behaviour?? (return None or raise StopIteration) + raise IndexError, 'at first element.' + return self.__create_context__(self._parent, *parent_node.itemat(i-1)) + # XXX should this support root ('/') + @property + def path(self): + ''' + ''' + node = self + res = [] + while node._parent != None: + res += [node._key] + node = node._parent + res.reverse() + return res + # XXX is this good? + @property + def type(self): + return self._node.__class__.__name__ + + + + def __init__(self, parent_context, key, node): + ''' + ''' + self._parent = parent_context + self._key = key + self._node = node + # XXX do we need this to proxy anything else? + # XXX add constructors... (code from testsys/tags?) + def __getattr__(self, name): + ''' + select next context. + ''' + return self.__create_context__(self, name, self._node[name]) + __getitem__ = __getattr__ + # specific interface... + def __create_context__(self, context, key, node): + ''' + ''' + return self.__class__(context, key, node) + + # editing... + def rename(self, name): + ''' + + NOTE: the name is relative to the context. if several containers + reference this node, only the one directly above in the + current context will be changed. + ''' + p_node = self._parent._node + # XXX possible race condition... + p_node.insertbefore(self._key, name, self._node) + del p_node[self._key] + self._key = name + def shift(self, offset): + ''' + ''' + self._parent._node.shift(offset, self._key) + def remove(self): + ''' + ''' + del self._parent._node[self._key] + ##!!! + def unwrap(self): + ''' + replace node with it's contents. + ''' + # XXX check if self is a container... + pass + ##!!! +## def wraprangewith(self, start, end, container): +## ''' +## ''' +## pass + ##!!! + def moveto(self, context, key): + ''' + ''' + pass + ##!!! + def copyto(self, context, key): + ''' + ''' + pass + + # proxy functionality to the node... + ##!!! + + +#----------------------------------------------------------------------- +# tempates... +# +# templates are comprised of two parts: +# - the template itself. +# a structure used by the renderer. defines structure, fields and +# rules.... (XXX anything else?) +# - the reference or usage of a template. +# a template reference or usage is the filled fields for a +# template and a reference to it. +# * the context sees the expanded tree (but templated nodes are marked). +# * templates can be expanded (e.g. turned into normal nodes). +class Template(Node): + ''' + ''' + pass + + + +#----------------------------------------------------------------------- +if __name__ == '__main__': + + nc = NodeContainer() + context = NodeContext(None, None, nc) + + for k in 'abcdefg': + nc[k] = nc + + nc['text'] = 'some text...' + + print nc.keys() + nc.reverse() + print nc.keys() + print nc['c'], nc.index('c'), nc.itemat(nc.index('c')) + print + print nc.keys() + nc.shift(10, 'c') + print nc.keys() + print nc.keyat(4) + nc.shift(-2, 'c') + print nc.keys() + # and we even support slices! :)))) + print nc['d':'a':2] + print + print nc.keys() + print context.c.name + print context.c.prev.name + print context.c.next.name + print context.c.parent.name + print context.c.a.text.name + print context.c.a.text.parent.name + print + print context.c.name + context.c.name = 'aaa' + print context.aaa.name + print nc.keys() + context.aaa.shift(-2) + print nc.keys() + context.aaa.remove() + print nc.keys() + + print '-'*80 + + pages = NodeContainer() + root = NodeContext(None, None, pages) + + # XXX use constructors... + pages['first page'] = NodeContainer() + pages['second page'] = NodeContainer() + pages['third page'] = NodeContainer() + + pages['first page']['001'] = NodeContainer() + pages['first page']['001'][001] = NodeContainer() + pages['first page']['002'] = NodeContainer() + pages['first page']['002'][001] = NodeContainer() + pages['first page']['003'] = NodeContainer() + pages['first page']['003'][001] = NodeContainer() + pages['first page']['003'][002] = pages['second page'] + + + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/pli-structdoc/structure.py b/pli-structdoc/structure.py new file mode 100755 index 0000000..7cbc424 --- /dev/null +++ b/pli-structdoc/structure.py @@ -0,0 +1,463 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20080311152519''' +__copyright__ = '''(c) Alex A. Naanou 2008''' + + +#----------------------------------------------------------------------- + +import pli.structdoc.core as core + +from pli.functional import curry +import time + + +#----------------------------------------------------------------------- +# +# XXX use templates and direct HTML representation for rendering... +# Tree ---(template)--> HTML --> file +# XXX clean things up... +# +# +#----------------------------------------------------------------------- +# specifics... +#-------------------------------------------------------NodeContainer--- +class NodeContainer(core.NodeContainer): + ''' + ''' + def __init__(self, *nodes): + ''' + ''' + ##!!! this is not the best wat to go... + super(NodeContainer, self).__init__() + # add nodes... + for n in nodes: + if 'title' in n: + i = n['title'] + else: + i = self._get_unique_key() + self[i] = n + def _get_unique_key(self): + ''' + ''' + key = str(time.time()) + while key in self.keys(): + key = str(time.time()) + return key + + +##---------------------------------------------NodeContainerWithTitle--- +class NodeContainerWithTitle(NodeContainer): + ''' + ''' + def __init__(self, title, *nodes): + ''' + ''' + super(NodeContainerWithTitle, self).__init__(*nodes) + self['title'] = title + + +#----------------------------------------------------------------------- +#----------------------------------------------------------------Site--- +class Site(NodeContainerWithTitle): + ''' + can contain any number of nodes. + ''' + pass + + +#----------------------------------------------------------------Page--- +class Page(NodeContainerWithTitle): + ''' + can contain any number of nodes. + ''' + pass + + +#-------------------------------------------------------------Section--- +class Section(NodeContainerWithTitle): + ''' + can contain any number of nodes. + ''' + pass + + +#----------------------------------------------------------------Text--- +class Text(NodeContainer): + ''' + ''' + pass + + +#---------------------------------------------------------------Group--- +class Group(NodeContainer): + ''' + ''' + pass + + +#----------------------------------------------------------------Link--- +class Link(NodeContainer): + ''' + contains two nodes: + - text + - any node (usually a container) + ''' + def __init__(self, title, obj): + ''' + ''' + super(Link, self).__init__() + self['title'] = title + self['obj'] = obj + + + +#----------------------------------------------------------------------- +# render... +# +# target backends: +# - text +# - html (view) +# - html (edit) -- combined with view +# - XXX +# +# * might be a good idea to implement the render as a template... +#------------------------------------------------------BaseRSTContext--- +class BaseRSTContext(core.NodeContext): + ''' + ''' + # render nodes... + @property + def rst(self): + ''' + ''' + return self._rst_node(1, self._node, cache=set()) + # render sections... + def _rst_str(self, node, cache=None): + ''' + ''' + return node + def _rst_unknown(self, level, node, cache=None): + ''' + ''' + return '\n' + ' '*(level-1) + '''%(node_name)s %(title)s:\n%(content)s'''\ + % dict( + title=repr(node.get('title', '')), + node_name=node.__class__.__name__, + content=('\n' + ' '*(level-1)).join([self._rst_node(level+1, node[n], cache=cache) \ + for n in node.keys() \ + if n != 'title' ])) + '\n' + def _rst_node(self, level, node, cache=None): + ''' + ''' + t = type(node) + # avoid recursion... + if node in cache: + if 'title' in node: + t = node['title'] + else: + # guess some text... + t = '.....' + return self._rst_node(level, Text(Link(t, node)), cache) + else: + cache.add(node) + # strings... + if t in (str, unicode): + return self._rst_str(node, cache=cache) + return self._rst_unknown(level, node, cache=cache) + + +#----------------------------------------------------------RSTContext--- +# XXX write a node generator (rst-tree) +# XXX needs a selector... +##class RSTContext(core.NodeContext): +class RSTContext(BaseRSTContext): + ''' + ''' + # render sections... + def _rst_page(self, node, cache=None): + ''' + ''' + return '''%(title)s\n----\n%(content)s'''\ + % dict( + title=node['title'], + content='\n'.join([self._rst_node(1, node[n], cache=cache) \ + for n in node.keys() \ + if n != 'title'])) + def _rst_section(self, level, node, cache=None): + ''' + ''' + return '\n' + ' '*(level-1) + '''%(q)s %(title)s %(q)s\n%(content)s'''\ + % dict( + q='='*level, + title=node['title'], + content=('\n' + ' '*(level-1)).join([self._rst_node(level+1, node[n], cache=cache) \ + for n in node.keys() \ + if n != 'title'])) + '\n' + def _rst_text(self, level, node, cache=None): + ''' + ''' +## return '\n' + ' '.join([ self._rst_node(level, node[n]) \ + return '\n' + ' '*(level-1) + ' '.join([ self._rst_node(level, node[n], cache=cache) \ + for n in node.keys() ]) + def _rst_link(self, node, cache=None): + ''' + ''' + return '[[%(title)s|%(url)s|%(alt)s]]' \ + % dict( + title=node['title'], + url='mooo', + alt='foo') + ##!!! make this extend BaseRSTContext._rst_node... + def _rst_node(self, level, node, cache=None): + ''' + ''' + t = type(node) + # avoid recursion... + if node in cache: + if 'title' in node: + t = node['title'] + else: + # guess some text... + t = '.....' + return self._rst_node(level, Text(Link(t, node)), cache) + else: + cache.add(node) + # pages... + if t is Page: + return self._rst_page(node, cache=cache) + # links and refs... + elif t is Link: + return self._rst_link(node, cache=cache) + # sections... + elif t is Section: + return self._rst_section(level, node, cache=cache) + # text blocks... + elif t is Text: + return self._rst_text(level, node, cache=cache) + # strings... + elif t in (str, unicode): + return self._rst_str(node, cache=cache) + return self._rst_unknown(level, node, cache=cache) + + # XXX node generator.... (rst input...) + ##!!! + + +#---------------------------------------------------------HTMLContext--- +# NOTE: this will not create pretty HTML, it was not the goal... +# XXX this does not consider titles as nodes... (wrong?) +class HTMLContext(core.NodeContext): + ''' + ''' + # templates... + # XXX move these to files... + _templates = ( + 'html', + 'page', + 'section', + 'text', + 'emphasized', + 'link', + 'unknown', + ) + ##!!! this is wrong.... should dynamicly figure this out... + _template_dir = './templates/plain/' + + # props... + # XXX move this to someplace more generic... + @property + def rawhtml(self): + cache = set() + return self.html_tpl \ + % dict( + title=self.name, + content=self._html_node(self, 1, self._node, cache=cache)) + # XXX make this the default... + @property + def html(self): + ''' + render page html + ''' + cache = set() + node = self._get_page() + return self.html_tpl \ + % dict( + title=self._node['title'], + content=node._html_page(self, 1, node._node, self._node, cache=cache)) + ##!!! STUB -- need to create a real relative or server absolute URL... (will depend on server) + # XXX need to find the shortest path form node to root or to + # current page (site-absolute or relative). + @property + def url(self, target=None): + ''' + + NOTE: if target is omited then return url to self. + ''' + if target == None: + return '/' + '/'.join(self.path) + # XXX search.... + raise NotImplementedError + + + def __init__(self, *p, **n): + ''' + ''' + super(HTMLContext, self).__init__(*p, **n) + self._reload_templates() + + # helpers... + def _get_page(self): + ''' + get the nearest page up in the context... + ''' + node = self + # get parent page... + while node.type != 'Page': + node = node.parent + return node + def _reload_templates(self): + ''' + ''' + for tpl in self._templates: + setattr(self, tpl + '_tpl', file('%s/%s.tpl' % (self._template_dir, tpl), 'r').read()) + # processors... + def _html_page(self, context, level, page, emphasize=None, cache=None): + ''' + ''' + return self.page_tpl \ + % dict( + title=page['title'], + content=''.join([ self._html_node(context, level, page[n], emphasize=emphasize, cache=cache) \ + for n in page.keys() \ + if n != 'title' ])) + def _html_emphasized(self, context, level, node, cache=None): + ''' + ''' + cache.discard(node) + return self.emphasized_tpl \ + % dict( + content=self._html_node(context, level, node, cache=cache)) + def _html_section(self, context, level, section, emphasize, cache=None): + if level > 6: + raise ValueError, 'html sections do not support nesting level greater than 6 (got %s)' % level + return self.section_tpl \ + % dict( + level=level, + title=section['title'], + content=''.join([ self._html_node(context, level+1, section[n], emphasize, cache=cache) \ + for n in section.keys() \ + if n != 'title' ])) + def _html_text(self, context, level, node, cache=None): + ''' + ''' + return self.text_tpl \ + % ' '.join([ self._html_node(context, level+1, node[n], cache=cache) for n in node.keys() ]) + def _html_str(self, context, node, cache=None): + ''' + ''' + return node + # XXX need to get the referenced object via the context... + def _html_link(self, context, node, cache=None): + ''' + ''' + return self.link_tpl \ + % dict( +## url=node.obj.url, + url='mooo', + alt='fooo', + title=node['title']) + def _html_unknown(self, context, level, node, emphasize, cache=None): + ''' + ''' + return self.unknown_tpl \ + % dict( + level=level, + node_name=node.__class__.__name__, + content=''.join([ self._html_node(context, level, node[n], + emphasize=emphasize, cache=cache) \ + for n in node.keys() ])) + def _html_node(self, context, level, node, emphasize=None, cache=None): + t = type(node) + # avoid recursion... + if node in cache: + if 'title' in node: + t = node['title'] + else: + # guess some text... + t = '.....' + return self._html_node(context, level, Text(Link(t, node)), emphasize, cache) + else: + cache.add(node) + # links and refs... + if node == emphasize: + return self._html_emphasized(context, level, node, cache=cache) + elif t is Link: + return self._html_link(context, node, cache=cache) + # sections... + elif t is Section: + return self._html_section(context, level, node, emphasize, cache=cache) + # pages... + elif t is Page: + return self._html_section(context, level, node, emphasize, cache=cache) + # text blocks... + elif t is Text: + return self._html_text(context, level, node, cache=cache) + # strings... + elif t in (str, unicode): + return self._html_str(context, node, cache=cache) + return self._html_unknown(context, level, node, emphasize, cache=cache) + + +#---------------------------------------------------RawRSTHTMLContext--- +class RawRSTHTMLContext(HTMLContext, BaseRSTContext): + ''' + ''' + pass + + +#------------------------------------------------------RSTHTMLContext--- +class RSTHTMLContext(HTMLContext, RSTContext): + ''' + ''' + pass + + + +#----------------------------------------------------------------------- +if __name__ == '__main__': + + from test_page import root + + # render and save by path... + def render(path, format='html', ext=None): + # parse path... + path = path.split('/') + while '' in path: + path.remove('') + cur = root + # get the node... + for n in path: + cur = cur[n] + if ext == None: + ext = format + # render and save to file.... + file('./test/%s.%s' % (cur.name, ext), 'w').write(getattr(cur, format)) + + + render('/p') + render('/p/first section/') + render('p/first section/', format='rawhtml', ext='raw.html') + render('p/first section/nested section/') + render('p/first section/nested section/another nested section') + + render('/p', format='rst') + render('/p/first section/', format='rst') + render('p/first section/nested section/', format='rst') + + + + + +#=======================================================================|# vim:set ts=4 sw=4 nowrap : diff --git a/pli-structdoc/templates/plain/emphasized.tpl b/pli-structdoc/templates/plain/emphasized.tpl new file mode 100755 index 0000000..45e0c5a --- /dev/null +++ b/pli-structdoc/templates/plain/emphasized.tpl @@ -0,0 +1 @@ +
%(content)s
diff --git a/pli-structdoc/templates/plain/general.css b/pli-structdoc/templates/plain/general.css new file mode 100755 index 0000000..466d51b --- /dev/null +++ b/pli-structdoc/templates/plain/general.css @@ -0,0 +1,22 @@ +.section .section { + margin-left: 2em; + padding-left: 0.5em; + border-left: 0.1em solid #eeeeee; +} +body .section { + padding-left: 0.5em; +} +.page_title { + padding: 0.2em; + border-bottom: 0.1em solid black; +} + +.emphasized_block { + margin: 0em; + padding: 0.2em; + border: 0.2em solid #ccc; + background-color: #fafafa; +} + +.unknown_node { +} diff --git a/pli-structdoc/templates/plain/html.tpl b/pli-structdoc/templates/plain/html.tpl new file mode 100755 index 0000000..eefadba --- /dev/null +++ b/pli-structdoc/templates/plain/html.tpl @@ -0,0 +1,9 @@ + + + %(title)s + + + + %(content)s + + diff --git a/pli-structdoc/templates/plain/link.tpl b/pli-structdoc/templates/plain/link.tpl new file mode 100755 index 0000000..7716a08 --- /dev/null +++ b/pli-structdoc/templates/plain/link.tpl @@ -0,0 +1 @@ +%(title)s diff --git a/pli-structdoc/templates/plain/page.tpl b/pli-structdoc/templates/plain/page.tpl new file mode 100755 index 0000000..c90a2d2 --- /dev/null +++ b/pli-structdoc/templates/plain/page.tpl @@ -0,0 +1,2 @@ +

%(title)s

+%(content)s diff --git a/pli-structdoc/templates/plain/section.tpl b/pli-structdoc/templates/plain/section.tpl new file mode 100755 index 0000000..e2d1d5a --- /dev/null +++ b/pli-structdoc/templates/plain/section.tpl @@ -0,0 +1,4 @@ +
+ %(title)s + %(content)s +
diff --git a/pli-structdoc/templates/plain/text.tpl b/pli-structdoc/templates/plain/text.tpl new file mode 100755 index 0000000..b4ecd96 --- /dev/null +++ b/pli-structdoc/templates/plain/text.tpl @@ -0,0 +1 @@ +

%s

diff --git a/pli-structdoc/templates/plain/unknown.tpl b/pli-structdoc/templates/plain/unknown.tpl new file mode 100755 index 0000000..9c2b48d --- /dev/null +++ b/pli-structdoc/templates/plain/unknown.tpl @@ -0,0 +1 @@ +
%(content)s
diff --git a/pli-structdoc/test/general.css b/pli-structdoc/test/general.css new file mode 100755 index 0000000..77a7984 --- /dev/null +++ b/pli-structdoc/test/general.css @@ -0,0 +1,25 @@ +.section .section { + margin-left: 2em; + padding-left: 0.5em; + border-left: 0.1em solid #eeeeee; +} +body .section { + padding-left: 0.5em; +} +.page_title { + padding: 0.2em; + border-bottom: 0.1em solid black; +} + +.emphasized_block { + margin: 0em; + padding: 0.2em; + border: 0.2em solid #ccc; + background-color: #fafafa; +} + +/* nodes that are not known by the render... + */ +.unknown_node { + border: 0.1em dotted red; +} diff --git a/pli-structdoc/test_page.py b/pli-structdoc/test_page.py new file mode 100755 index 0000000..72c5fdd --- /dev/null +++ b/pli-structdoc/test_page.py @@ -0,0 +1,46 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20080310204420''' +__copyright__ = '''(c) Alex A. Naanou 2008''' + + +#----------------------------------------------------------------------- + +from structure import Site, Page, Section, Text, Link, Group, RSTHTMLContext, RawRSTHTMLContext + + +#----------------------------------------------------------------------- + +# setup the root and context... +site = Site('root') +##root = RawRSTHTMLContext(None, None, site) +root = RSTHTMLContext(None, None, site) + +# now for the data/pages... +site['m'] = Page('first page', + Section('section', + Text('text'))) +site['p'] = Page('test page', + Section('first section', + Text('a section can contain several nodes in it\'s body.'), + Section('nested section', + Group( + Text('nested sections are just like normal sections but are nested in other sections'), + Text('there can be as many nesting levels as needed.')), + Section('another nested section', + Text('with some text...')), + '....')), + Section('second section', + Text('this is an example of a ', + Link('link', site['m']), + 'to another page...')), + # direct node inclusion.... + site['m']) +# in-page recursion.... +site['p']['moo'] = site['p']['first section']['nested section'] + + + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : diff --git a/pli-structdoc/test_srv.py b/pli-structdoc/test_srv.py new file mode 100755 index 0000000..92faba9 --- /dev/null +++ b/pli-structdoc/test_srv.py @@ -0,0 +1,56 @@ +#======================================================================= + +__version__ = '''0.0.01''' +__sub_version__ = '''20080307035538''' +__copyright__ = '''(c) Alex A. Naanou 2008''' + + +#----------------------------------------------------------------------- + +from twisted.web import server, resource +from twisted.internet import reactor + +from test_page import root + + +#----------------------------------------------------------------------- + +# NOTE: set this to None to disable caching... +cache = {} + +class Fetcher(resource.Resource): + isLeaf = True + + def render_GET(self, request): + path = request.postpath[:] + format = 'html' + if path[-1] == 'general.css': + return file('test/general.css', 'r').read() + if path[-1].split('.')[-1] in ('html', 'rst', 'rawhtml'): + path[-1], format = path[-1].split('.') + cur = root + for p in path: + if p == '': + continue + cur = cur[p] + # do some caching... + # XXX this caching is brain-dead :) + if cache != None: + if (cur, format) in cache: + return cache[(cur, format)] + res = cache[(cur, format)] = getattr(cur, format) + return res + else: + return getattr(cur, format) + + +#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +site = server.Site(Fetcher()) +reactor.listenTCP(8080, site) +reactor.run() + + + +#======================================================================= +# vim:set ts=4 sw=4 nowrap : -- 2.11.4.GIT