diff --git a/wiki/README.txt b/wiki/README.txt new file mode 100644 index 0000000..a204dc7 --- /dev/null +++ b/wiki/README.txt @@ -0,0 +1,35 @@ +============================== +Yet Another WikiWiki Framework +============================== + + ($Id$) + + +Links and Link Management +========================= + + >>> from cybertools.wiki.base import link + + >>> manager = link.LinkManager() + + >>> input = ('This is text with a [[wikilink Wiki Link]] and a ' + ... '`RestructuredText Link `__') + + >>> page = object() + >>> format = link.DoubleBracketLinkFormat(page) + >>> format.manager = manager + + >>> format.unmarshall(input) + 'This is text with a [[##0000001##]] and a `RestructuredText Link `__' + + >>> link = manager.links['0000001'] + + >>> link.original + '[[wikilink Wiki Link]]' + + >>> link.target + 'wikilink' + + >>> link.label + 'Wiki Link' + diff --git a/wiki/__init__.py b/wiki/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/wiki/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/wiki/base/__init__.py b/wiki/base/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/wiki/base/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/wiki/base/link.py b/wiki/base/link.py new file mode 100644 index 0000000..3641326 --- /dev/null +++ b/wiki/base/link.py @@ -0,0 +1,105 @@ +# +# 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 (sample) implementations for links and link management + +$Id$ +""" + +import re +from zope.interface import implements + +from cybertools.wiki.interfaces import ILink, ILinkFormat, ILinkManager + + +class Link(object): + + implements(ILink) + + identifier = None + manager = None + formatName = None + + def __init__(self, source, target): + self.source = source + self.target = target + + +class BaseLinkFormat(object): + + implements(ILinkFormat) + + manager = None + + name = 'base' + internalFormat = '##%s##' + internalRegexp = re.compile(r'##(.+)##(.+)##') + + def __init__(self, context): + self.context = context + + def unmarshall(self, text): + return self.externalRegexp.sub(self.processLink, text) + + def marshall(self, text): + return text + + def display(self, text): + return 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.manager.register(link) + return self.externalFormat % (self.internalFormat % link.identifier) + + +class DoubleBracketLinkFormat(BaseLinkFormat): + + name = 'doublebracket' + externalFormat = '[[%s]]' + externalRegexp = re.compile(r'\[\[(.+)\]\]') + + +class LinkManager(object): + + implements(ILinkManager) + + def __init__(self): + self.links = {} + + def register(self, link): + if link.identifier is None: + self.generateIdentifier(link) + if link.identifier not in self.links: + self.links[link.identifier] = link + link.manager = self + + def unregister(self, link): + if link.identifier in self.links: + del self.links[link.identifier] + link.manager = None + + def generateIdentifier(self, link): + identifier = '%07i' % (max(self.links.keys() or [0]) + 1) + link.identifier = identifier + return identifier + diff --git a/wiki/interfaces.py b/wiki/interfaces.py new file mode 100644 index 0000000..3a3c0b5 --- /dev/null +++ b/wiki/interfaces.py @@ -0,0 +1,83 @@ +# +# 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 +# + +""" +Interfaces for Wiki functionality. + +$Id$ +""" + +from zope.interface import Interface, Attribute + + +# links + +class ILinkManager(Interface): + """Manages (and possibly contains) links of all kinds. + """ + + def register(link): + """Register (store) a link. + """ + + def unregister(link): + """Remove a link. + """ + + +class ILink(Interface): + """A hyperlink between two local or foreign objects. + """ + + identifier = Attribute('Identifier of the link, unique within its link manager.') + manager = Attribute('The manager that this link is managed by.') + formatName = Attribute('Name of the link format that identified the link.') + + source = Attribute('Link source.') + target = Attribute('Link target.') + + +class ILinkFormat(Interface): + """Identifies links in texts and transforms text correspondingly. + """ + + manager = Attribute('The link manager this link format is associated with.') + + 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. + """ diff --git a/wiki/tests.py b/wiki/tests.py new file mode 100755 index 0000000..549519f --- /dev/null +++ b/wiki/tests.py @@ -0,0 +1,28 @@ +#! /usr/bin/python + +""" +Tests for the 'cybertools.wiki' package. + +$Id$ +""" + +import unittest, doctest +from zope.testing.doctestunit import DocFileSuite + + +class Test(unittest.TestCase): + "Basic tests for the wiki package." + + def testBasicStuff(self): + pass + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + return unittest.TestSuite(( + unittest.makeSuite(Test), + DocFileSuite('README.txt', optionflags=flags), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite')