1.1 --- a/README.txt Sun Nov 03 01:03:35 2013 +0100
1.2 +++ b/README.txt Sun Nov 03 14:52:17 2013 +0100
1.3 @@ -66,6 +66,12 @@
1.4 Here, CCDIR is the path to the top level of this source distribution where
1.5 this README.txt file is found.
1.6
1.7 +When importing users, MoinMoin may be unable to handle user information
1.8 +containing non-ASCII characters. Another patch to solve such problems can be
1.9 +applied to MoinMoin as follows:
1.10 +
1.11 +patch -p1 $CCDIR/patches/patch-moin-1.9-MoinMoin-user.diff
1.12 +
1.13 Wiki Content Prerequisites
1.14 --------------------------
1.15
1.16 @@ -73,18 +79,12 @@
1.17 required:
1.18
1.19 http://moinmo.in/ParserMarket/ImprovedTableParser
1.20 -http://hgweb.boddie.org.uk/MoinSupport
1.21 +http://moinmo.in/ActionMarket/SubpageComments
1.22 http://moinmo.in/MacroMarket/Color2
1.23
1.24 -In addition, extensions are provided in this distribution to support various
1.25 -Confluence features, notably comments on pages. These extensions are installed
1.26 -as follows:
1.27 +A common dependency of various extensions is provided by MoinSupport:
1.28
1.29 -python moinsetup.py -m install_actions $CCDIR/actions
1.30 -python moinsetup.py -m install_macros $CCDIR/macros
1.31 -python moinsetup.py -m install_theme_resources $CCDIR
1.32 -python moinsetup.py -m edit_theme_stylesheet screen.css includecomments.css
1.33 -python moinsetup.py -m edit_theme_stylesheet print.css includecomments.css
1.34 +http://hgweb.boddie.org.uk/MoinSupport
1.35
1.36 Additional Software
1.37 -------------------
2.1 --- a/actions/PostComment.py Sun Nov 03 01:03:35 2013 +0100
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,128 +0,0 @@
2.4 -# -*- coding: iso-8859-1 -*-
2.5 -"""
2.6 - MoinMoin - PostComment action
2.7 -
2.8 - @copyright: 2013 by Paul Boddie <paul@boddie.org.uk>
2.9 - @license: GNU GPL (v2 or later), see COPYING.txt for details.
2.10 -"""
2.11 -
2.12 -from MoinMoin.action import ActionBase
2.13 -from MoinMoin.PageEditor import PageEditor
2.14 -from MoinMoin.security import Permissions
2.15 -from MoinMoin.wikiutil import escape
2.16 -from MoinSupport import getPagesForSearch, getPagesFromResults, ActionSupport
2.17 -
2.18 -Dependencies = ['pages']
2.19 -
2.20 -class SpecialPermissions(Permissions):
2.21 -
2.22 - "Permit saving of ACL-enabled comment pages."
2.23 -
2.24 - def __init__(self, user, pagename):
2.25 - Permissions.__init__(self, user)
2.26 - self.pagename = pagename
2.27 -
2.28 - def admin(self, pagename):
2.29 - return pagename == self.pagename
2.30 -
2.31 -class PostComment(ActionBase, ActionSupport):
2.32 -
2.33 - "Post a comment to the wiki."
2.34 -
2.35 - def get_form_html(self, buttons_html):
2.36 -
2.37 - "Return the action's form incorporating the 'buttons_html'."
2.38 -
2.39 - _ = self._
2.40 - request = self.request
2.41 - form = self.get_form()
2.42 -
2.43 - comment = form.get("comment", [""])[0]
2.44 -
2.45 - d = {
2.46 - "comment_label" : escape(comment and _("Please review your comment.") or _("Write a comment in the box.")),
2.47 - "comment_default" : escape(comment),
2.48 - "buttons_html" : buttons_html,
2.49 - }
2.50 -
2.51 - return u"""\
2.52 -<p>%(comment_label)s</p>
2.53 -<textarea name="comment" cols="60" rows="10">%(comment_default)s</textarea>
2.54 -<p>%(buttons_html)s</p>
2.55 -""" % d
2.56 -
2.57 - def do_action(self):
2.58 -
2.59 - "Attempt to post a comment."
2.60 -
2.61 - _ = self._
2.62 - request = self.request
2.63 - form = self.get_form()
2.64 -
2.65 - comment = form.get("comment", [""])[0]
2.66 -
2.67 - if not comment.strip():
2.68 - return 0, _("A comment should have some content.")
2.69 -
2.70 - if not request.user.valid or not request.user.may.write(self.pagename):
2.71 - return 0, _("You are not allowed to comment on this page.")
2.72 -
2.73 - # Determine the last comment.
2.74 -
2.75 - comments = get_comment_numbers(self.pagename, request)
2.76 - last_comment_pagename = comments and comments[-1] or -1
2.77 -
2.78 - # Write the new page.
2.79 -
2.80 - comment_pagename = "%s/%04d" % (self.pagename, last_comment_pagename + 1)
2.81 - new_page = PageEditor(request, comment_pagename)
2.82 - username = request.user.name
2.83 -
2.84 - try:
2.85 - # To add a page with an ACL, a special policy is required.
2.86 -
2.87 - may = request.user.may
2.88 - request.user.may = SpecialPermissions(request.user, comment_pagename)
2.89 -
2.90 - # Save the page, labelling it with the actual username.
2.91 -
2.92 - try:
2.93 - new_page.saveText(comment_template % (username, username, comment), 0)
2.94 -
2.95 - # Restore the superusers.
2.96 -
2.97 - finally:
2.98 - request.user.may = may
2.99 -
2.100 - return 1, _("Comment added.")
2.101 - except new_page.SaveError, exc:
2.102 - return 0, unicode(exc)
2.103 -
2.104 -comment_template = """\
2.105 -#acl %s:read,write,delete,revert All:read
2.106 -#pragma comment-owner %s
2.107 -%s"""
2.108 -
2.109 -def get_comment_numbers(pagename, request):
2.110 -
2.111 - """
2.112 - Return a list of comment numbers associated with the given 'pagename', using
2.113 - the 'request' provided.
2.114 - """
2.115 -
2.116 - pagenames = []
2.117 -
2.118 - for page in getPagesForSearch("title:regex:^%s/" % pagename, request):
2.119 - basename, number = page.page_name.rsplit("/", 1)
2.120 - if basename == pagename and number.isdigit():
2.121 - pagenames.append(int(number))
2.122 -
2.123 - pagenames.sort()
2.124 - return pagenames
2.125 -
2.126 -# Action invocation function.
2.127 -
2.128 -def execute(pagename, request):
2.129 - PostComment(pagename, request).render()
2.130 -
2.131 -# vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/css/includecomments.css Sun Nov 03 01:03:35 2013 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,43 +0,0 @@
3.4 -/* includecomments.css - some additional styles for the IncludeComments macro
3.5 - which can be included in screen.css and print.css
3.6 - using...
3.7 -
3.8 - @import "includecomments.css";
3.9 -
3.10 - ...before any rules.
3.11 -
3.12 -Copyright (c) 2013 by Paul Boddie
3.13 -Licensed under the GNU GPL (v2 or later), see COPYING.txt for details.
3.14 -*/
3.15 -
3.16 -.included-comment {
3.17 - margin: 1em;
3.18 - border: 2px solid #ddd;
3.19 - padding: 1em;
3.20 -}
3.21 -
3.22 -.included-comment-owner {
3.23 - float: left;
3.24 - clear: left;
3.25 - margin-right: 1em;
3.26 - padding: 0.5em;
3.27 - background-color: #ddd;
3.28 - color: #000;
3.29 - font-weight: bold;
3.30 - font-size: larger;
3.31 -}
3.32 -
3.33 -/* Hide the link to the comment form when showing the form. */
3.34 -
3.35 -#includecomments-anchor:target > a {
3.36 - display: none;
3.37 -}
3.38 -
3.39 -/* Hide the comment form unless the link has been followed. */
3.40 -
3.41 -#includecomments-anchor:not(:target) .includecomments-form {
3.42 - display: none;
3.43 -}
3.44 -
3.45 -/* vim: tabstop=4 expandtab shiftwidth=4
3.46 - */
4.1 --- a/macros/IncludeComments.py Sun Nov 03 01:03:35 2013 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,157 +0,0 @@
4.4 -# -*- coding: iso-8859-1 -*-
4.5 -"""
4.6 - MoinMoin - IncludeComments Macro
4.7 -
4.8 - @copyright: 2013 by Paul Boddie <paul@boddie.org.uk>
4.9 - @license: GNU GPL (v2 or later), see COPYING.txt for details.
4.10 -
4.11 - Code from the Include macro:
4.12 -
4.13 - @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
4.14 - 2000-2001 Richard Jones <richard@bizarsoftware.com.au>
4.15 - @license: GNU GPL (v2 or later), see COPYING.txt for details.
4.16 -"""
4.17 -
4.18 -from MoinMoin.Page import Page
4.19 -from MoinMoin.macro import Include
4.20 -from MoinMoin.user import User
4.21 -from MoinMoin.wikiutil import escape
4.22 -import re
4.23 -import codecs
4.24 -
4.25 -try:
4.26 - from cStringIO import StringIO
4.27 -except ImportError:
4.28 - from StringIO import StringIO
4.29 -
4.30 -Dependencies = ['pages']
4.31 -
4.32 -# Macro functions.
4.33 -
4.34 -def execute(macro, text):
4.35 - request = macro.request
4.36 - fmt = request.formatter
4.37 - page = request.page
4.38 - pagename = page.page_name
4.39 - _ = request.getText
4.40 -
4.41 - output = []
4.42 - append = output.append
4.43 -
4.44 - # Add a heading.
4.45 -
4.46 - append(fmt.heading(on=1, depth=1))
4.47 - append(fmt.text(_("Comments")))
4.48 - append(fmt.heading(on=0, depth=1))
4.49 -
4.50 - # Provide a form for adding new comments.
4.51 -
4.52 - if request.user.valid and request.user.may.write(pagename):
4.53 -
4.54 - d = {
4.55 - "show_form" : escape(_("Add a comment to this page.")),
4.56 - "comment_label" : escape(_("Write a comment in the box.")),
4.57 - "comment_default" : "",
4.58 - "submit" : escape(_("Submit this comment")),
4.59 - }
4.60 -
4.61 - append("""\
4.62 -<div id="includecomments-anchor">
4.63 -<a href="#includecomments-anchor">%(show_form)s</a>
4.64 -<form action="?action=PostComment" method="post" class="includecomments-form">
4.65 -<p>%(comment_label)s</p>
4.66 -<textarea name="comment" cols="60" rows="10">%(comment_default)s</textarea>
4.67 -<p><input name="submit" type="submit" value="%(submit)s" /></p>
4.68 -</form>
4.69 -</div>
4.70 -""" % d)
4.71 -
4.72 - # NOTE: Much of the code below originates from the Include macro, but it
4.73 - # NOTE: excludes various options of that macro and adds comment-related
4.74 - # NOTE: output.
4.75 -
4.76 - # Add included comments.
4.77 -
4.78 - filterfn = re.compile(ur"^%s/" % re.escape(pagename), re.U).match
4.79 - pages = request.rootpage.getPageList(filter=filterfn)
4.80 - pages.sort()
4.81 -
4.82 - ownerfn = re.compile("^#pragma comment-owner (.*?)$", re.MULTILINE | re.UNICODE).search
4.83 -
4.84 - # Track included pages.
4.85 -
4.86 - if not hasattr(page, '_macroInclude_pagelist'):
4.87 - page._macroInclude_pagelist = {}
4.88 -
4.89 - # Visit each comment page.
4.90 -
4.91 - for inc_name in pages:
4.92 -
4.93 - # Skip unreadable or already included pages.
4.94 -
4.95 - if not request.user.may.read(inc_name):
4.96 - continue
4.97 - if inc_name in page._macroInclude_pagelist:
4.98 - continue
4.99 -
4.100 - # Obtain a separate formatter for the included page.
4.101 -
4.102 - inc_fmt = macro.formatter.__class__(request, is_included=True)
4.103 - inc_fmt._base_depth = macro.formatter._base_depth
4.104 -
4.105 - # Obtain the included page.
4.106 -
4.107 - inc_page = Page(request, inc_name, formatter=inc_fmt)
4.108 - if not inc_page.exists():
4.109 - continue
4.110 - inc_page._macroInclude_pagelist = page._macroInclude_pagelist
4.111 -
4.112 - if not hasattr(request, "_Include_backto"):
4.113 - request._Include_backto = pagename
4.114 -
4.115 - # Output a container for the included page.
4.116 -
4.117 - append(fmt.div(1, id=inc_name, css_class="included-comment"))
4.118 -
4.119 - # Add a label indicating a comment.
4.120 -
4.121 - match = ownerfn(inc_page.get_raw_body())
4.122 - if match:
4.123 - user = User(request, auth_username=match.group(1))
4.124 - if user.exists():
4.125 - append(fmt.div(1, css_class="included-comment-owner"))
4.126 - append(fmt.text(user.aliasname or user.name))
4.127 - append(fmt.div(0))
4.128 -
4.129 - # Set or increment include marker.
4.130 -
4.131 - page._macroInclude_pagelist[inc_name] = \
4.132 - page._macroInclude_pagelist.get(inc_name, 0) + 1
4.133 -
4.134 - # Output the included page.
4.135 -
4.136 - strfile = codecs.getwriter("utf-8")(StringIO())
4.137 - request.redirect(strfile)
4.138 - try:
4.139 - inc_page.send_page(content_only=True,
4.140 - omit_footnotes=True,
4.141 - count_hit=False)
4.142 - append(unicode(strfile.getvalue(), "utf-8"))
4.143 - finally:
4.144 - request.redirect()
4.145 -
4.146 - # Decrement or remove include marker.
4.147 -
4.148 - if page._macroInclude_pagelist[inc_name] > 1:
4.149 - page._macroInclude_pagelist[inc_name] = \
4.150 - page._macroInclude_pagelist[inc_name] - 1
4.151 - else:
4.152 - del page._macroInclude_pagelist[inc_name]
4.153 -
4.154 - # Close the container for the included page.
4.155 -
4.156 - append(fmt.div(0))
4.157 -
4.158 - return u"".join(output)
4.159 -
4.160 -# vim: tabstop=4 expandtab shiftwidth=4