work in progress: process document tree

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@3143 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-01-11 19:20:43 +00:00
parent fdb814fed7
commit 1d4363f23c
8 changed files with 110 additions and 150 deletions

View file

@ -26,33 +26,11 @@ We format the content of the start page using the restructured text format.
The parser for restructured text and a corresponding HTML writer are the The parser for restructured text and a corresponding HTML writer are the
default plugins used, so we can already render the page as HTML. default plugins used, so we can already render the page as HTML.
>>> tree = startPage.parse()
>>> print startPage.render() >>> print startPage.render()
visiting document
visiting paragraph
visiting strong
visiting #text
<p><strong>Welcome to the Demo Wiki</strong></p> <p><strong>Welcome to the Demo Wiki</strong></p>
A Very Basic Wiki Format
========================
(this is probably obsolete, will be replaced by corresponding WikiPage
parsing and rendering functionality)
We first set up a format (a utility) and create a format instance
from it. The instance needs a wiki page as its context - to simplify
things during testing we just use a bare object.
>>> from cybertools.wiki.base.format import BasicFormat
>>> format = BasicFormat()
>>> page = object()
>>> instance = format.getInstance(page)
Now we enter some simple text and request the format instance to
unmarshall it, i.e. to convert it from the editable to the internal
representation.
>>> input = ('This is text with a [[Wiki Link]].\n\n'
... 'It also contains a second line.')
>>> instance.unmarshall(input)
'This is text with a [[${l0000001}]].\n\nIt also contains a second line.'

View file

@ -53,4 +53,4 @@ class WikiConfiguration(BaseConfiguration):
writer = 'docutils.html' writer = 'docutils.html'
parser = 'docutils.rstx' parser = 'docutils.rstx'
processor = 'standard'

View file

@ -1,81 +0,0 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Basic Wiki formatting.
$Id$
"""
import re
from zope.interface import implements
from cybertools.wiki.base.link import Link, LinkManager
from cybertools.wiki.interfaces import IFormat, IFormatInstance
class FormatInstance(object):
#implements(IFormatInstance)
parent = None
def __init__(self, context):
self.context = context
def unmarshall(self, text):
return self.parent.linkRegexp.sub(self.processLink, text)
def processLink(self, match):
ref, label = match.group(1).split(' ', 1)
link = Link(self.context, ref)
link.original = match.group(0)
link.label = label
self.parent.manager.registerLink(link)
return self.parent.linkFormat % (self.parent.internalFormat % link.identifier)
def marshall(self, text):
return text
def display(self, text):
return text
class BasicFormat(object):
#implements(IFormat)
name = 'basic'
instanceFactory = FormatInstance
internalRegexp = re.compile(r'!\\\$([_A-Z0-9a-z]+)|{(.+)}')
internalFormat = '${%s}'
linkRegexp = re.compile(r'\[\[(.+)\]\]')
linkFormat = '[[%s]]'
repository = None
def __init__(self, manager=None):
if manager is None:
manager = LinkManager()
self.manager = manager
def getInstance(self, context):
instance = self.instanceFactory(context)
instance.parent = self
return instance

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de # Copyright (c) 2009 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -22,7 +22,6 @@ Basic (sample) implementations for links and link management
$Id$ $Id$
""" """
import re
from zope.interface import implements from zope.interface import implements
from cybertools.wiki.interfaces import ILink, ILinkManager from cybertools.wiki.interfaces import ILink, ILinkManager

54
wiki/base/process.py Normal file
View file

@ -0,0 +1,54 @@
#
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Tree processor implementation
$Id$
"""
from zope.interface import implements
from zope.component import adapts
from cybertools.wiki.interfaces import ITreeProcessor, IWikiPage
class TreeProcessor(object):
""" The standard tree processor walking the tree and processing
the tree's nodes.
"""
implements(ITreeProcessor)
adapts(IWikiPage)
tree = None
def __init__(self, context):
self.context = context
def process(self):
self.tree.walk(Visitor(self.tree))
class Visitor(object):
def __init__(self, document):
self.document = document
def dispatch_visit(self, node):
print 'visiting', node.tagname

View file

@ -27,7 +27,7 @@ from zope.interface import implements
from cybertools.wiki.interfaces import IWikiConfiguration from cybertools.wiki.interfaces import IWikiConfiguration
from cybertools.wiki.interfaces import IWikiManager, IWiki, IWikiPage from cybertools.wiki.interfaces import IWikiManager, IWiki, IWikiPage
from cybertools.wiki.interfaces import IParser, IWriter from cybertools.wiki.interfaces import IParser, IWriter, ITreeProcessor
from cybertools.wiki.base.config import BaseConfiguration from cybertools.wiki.base.config import BaseConfiguration
@ -88,18 +88,34 @@ class WikiPage(BaseConfiguration):
self.title = title or name self.title = title or name
def render(self): def render(self):
return self.write(self.parse()) source = self.preprocess(self.text)
tree = self.parse(source)
self.process(tree)
result = self.write(tree)
return self.postprocess(result)
def parse(self): def parse(self, source):
parserName = self.getConfig('parser') parserName = self.getConfig('parser')
parser = component.getUtility(IParser, name=parserName) parser = component.getUtility(IParser, name=parserName)
return parser.parse(self.text) return parser.parse(source)
def write(self, tree): def write(self, tree):
writerName = self.getConfig('writer') writerName = self.getConfig('writer')
writer = component.getUtility(IWriter, name=writerName) writer = component.getUtility(IWriter, name=writerName)
return writer.write(tree) return writer.write(tree)
def preprocess(self, source):
return source
def process(self, tree):
processor = component.getAdapter(self, ITreeProcessor,
name=self.getConfig('processor'))
processor.tree = tree
processor.process()
def postprocess(self, result):
return result
# configuration # configuration
def getParent(self): def getParent(self):

View file

@ -92,17 +92,30 @@ class IWikiPage(Interface):
text = Attribute('The page content in input text format.') text = Attribute('The page content in input text format.')
def render(): def render():
""" Convert the text of the page to presentation format. """ Convert the source text of the page to presentation format.
""" """
def parse(): def parse(source):
""" Convert the text of the page to a document tree. """ Convert the source text of the page to a document tree.
""" """
def write(tree): def write(tree):
""" Convert the document tree given to presentation format. """ Convert the document tree given to presentation format.
""" """
def preprocess(source):
""" Modify the source text of the page before parsing it and return it.
"""
def process(tree):
""" Scan the tree, changing it if necessary and collecting
interesting information about the nodes, e.g. about links.
"""
def postprocess(result):
""" Modify the output of the write process and return it.
"""
# wiki plugins # wiki plugins
@ -123,6 +136,18 @@ class IWriter(Interface):
""" """
class ITreeProcessor(Interface):
""" Processes a document tree.
"""
context = Attribute('The wiki page from which the tree was generated.')
tree = Attribute('The tree to be processed.')
def process():
""" Do what is necessary.
"""
# wiki elements # wiki elements
class ILinkManager(Interface): class ILinkManager(Interface):
@ -152,36 +177,3 @@ class ILink(Interface):
source = Attribute('Link source.') source = Attribute('Link source.')
target = Attribute('Link target.') target = Attribute('Link target.')
class IFormat(Interface):
"""Identifies links in texts and transforms text correspondingly.
"""
manager = Attribute('The Wiki manager this format is associated with.')
class IFormatInstance(Interface):
def unmarshall(text):
"""Analyse the text given extracting all links and registering them
with the link manager; return text with all links transformed to
an internal link naming format.
This is typically used for preprocessing the text after editing.
"""
def marshall(text):
"""Scan text for all links (i.e. substrings corresponding to the
internal link naming format) and replace them with their external
format.
This is typically used for preparing a text for editing.
"""
def display(text):
"""Scan text for all links (i.e. substrings corresponding to the
internal link naming format) and replace them with their display
format.
The result will then be used for rendering by the text format.
"""

View file

@ -11,6 +11,7 @@ from zope.testing.doctestunit import DocFileSuite
from zope import component from zope import component
from cybertools.wiki.base.config import WikiConfiguration from cybertools.wiki.base.config import WikiConfiguration
from cybertools.wiki.base.process import TreeProcessor
from cybertools.wiki.dcu.html import Writer as DocutilsHTMLWriter from cybertools.wiki.dcu.html import Writer as DocutilsHTMLWriter
from cybertools.wiki.dcu.rstx import Parser as DocutilsRstxParser from cybertools.wiki.dcu.rstx import Parser as DocutilsRstxParser
@ -26,6 +27,7 @@ def setUp(testCase):
component.provideUtility(WikiConfiguration()) component.provideUtility(WikiConfiguration())
component.provideUtility(DocutilsHTMLWriter(), name='docutils.html') component.provideUtility(DocutilsHTMLWriter(), name='docutils.html')
component.provideUtility(DocutilsRstxParser(), name='docutils.rstx') component.provideUtility(DocutilsRstxParser(), name='docutils.rstx')
component.provideAdapter(TreeProcessor, name='standard')
def test_suite(): def test_suite():