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:
parent
fdb814fed7
commit
1d4363f23c
8 changed files with 110 additions and 150 deletions
|
@ -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.'
|
|
||||||
|
|
|
@ -53,4 +53,4 @@ class WikiConfiguration(BaseConfiguration):
|
||||||
|
|
||||||
writer = 'docutils.html'
|
writer = 'docutils.html'
|
||||||
parser = 'docutils.rstx'
|
parser = 'docutils.rstx'
|
||||||
|
processor = 'standard'
|
||||||
|
|
|
@ -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
|
|
|
@ -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
54
wiki/base/process.py
Normal 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
|
|
@ -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):
|
||||||
|
|
|
@ -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.
|
|
||||||
"""
|
|
||||||
|
|
|
@ -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():
|
||||||
|
|
Loading…
Add table
Reference in a new issue