# HG changeset patch # User Paul Boddie # Date 1334356936 -7200 # Node ID 60d3ee6ab9f1d157f9f800277f2f5cfc2d49de50 Added a library and parser for processing shared content. diff -r 000000000000 -r 60d3ee6ab9f1 MoinShare.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MoinShare.py Sat Apr 14 00:42:16 2012 +0200 @@ -0,0 +1,75 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - MoinShare library + + @copyright: 2011, 2012 by Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinSupport import * +from MoinMoin import wikiutil +import re + +escape = wikiutil.escape + +__version__ = "0.1" + +# More Moin 1.9 compatibility functions. + +def has_member(request, groupname, username): + if hasattr(request.dicts, "has_member"): + return request.dicts.has_member(groupname, username) + else: + return username in request.dicts.get(groupname, []) + +# Extraction of shared fragments. + +marker_regexp_str = r"([{]{3,}|[}]{3,})" +marker_regexp = re.compile(marker_regexp_str, re.MULTILINE | re.DOTALL) # {{{... or }}}... + +def getRegions(s): + + "Parse the string 's', returning a list of shared regions." + + regions = [] + marker = None + is_region = True + + for match_text in marker_regexp.split(s): + + # Capture section text. + + if is_region and marker: + regions[-1] += match_text + + # Handle section markers. + + elif not is_region: + + # Close any open sections, returning to exposed text regions. + + if marker: + if match_text.startswith("}") and len(marker) == len(match_text): + marker = None + + # Without a current marker, start a section if an appropriate marker + # is given. + + elif match_text.startswith("{"): + marker = match_text + regions.append("") + + # Markers and section text are added to the current region. + + regions[-1] += match_text + + # Exposed text is ignored. + + # The match text alternates between text between markers and the markers + # themselves. + + is_region = not is_region + + return regions + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 000000000000 -r 60d3ee6ab9f1 parsers/MoinShare.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parsers/MoinShare.py Sat Apr 14 00:42:16 2012 +0200 @@ -0,0 +1,116 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - MoinShare fragment parser + + @copyright: 2011, 2012 by Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinMoin import wikiutil + +try: + from hashlib import sha1 +except ImportError: + from sha import new as sha1 + +Dependencies = ["pages"] + +# Parser support. + +class Parser: + + """ + Format shared content fragments of the form... + + {{{#!MoinShare ref=fragment format=content-type + + Content... + }}} + """ + + def __init__(self, raw, request, **kw): + + """ + Initialise the parser with the given 'raw' data, 'request' and any + keyword arguments that may have been supplied. + """ + + self.raw = raw + self.request = request + + attrs, msg = wikiutil.parseAttributes(request, kw.get("format_args", "")) + + # The attributes returned from the formatting arguments are encoded like + # strings. + + quotes = '"' + "'" + + # Get any reference to another fragment. + + self.ref = (attrs.get("ref") or '').strip(quotes) + self.format_type = (attrs.get("format") or '').strip(quotes) + + def getFragmentIdentifier(self): + + "Make a unique identifier for the fragment." + + return sha1(self.raw).hexdigest() + + def format(self, fmt): + + "Format a fragment using the given formatter 'fmt'." + + request = self.request + page = request.page + _ = request.getText + + request.write(fmt.anchordef(self.getFragmentIdentifier())) + + request.write(fmt.div(1, css_class="moinsharefragment")) + request.write(self.formatText(self.raw, fmt)) + request.write(fmt.div(0)) + + def getFormat(self): + + "Get the format used on this page." + + return self.format_type + + def getParserClass(self, format): + + """ + Return a parser class for the given 'format', returning a plain text + parser if no parser can be found for the specified 'format'. + """ + + cfg = self.request.cfg + + try: + return wikiutil.searchAndImportPlugin(cfg, "parser", format or "wiki") + except wikiutil.PluginMissingError: + return wikiutil.searchAndImportPlugin(cfg, "parser", "plain") + + def formatText(self, text, fmt): + + """ + Format the given 'text' using the specified formatter 'fmt'. + """ + + request = self.request + page = fmt.page = request.page + format = self.getFormat() + + # Suppress line anchors. + + parser_cls = self.getParserClass(format) + parser = parser_cls(text, request, line_anchors=False) + + # Fix lists by indicating that a paragraph is already started. + + kw = {} + if not format or format == "wiki": + kw["inhibit_p"] = True + + return request.redirectedOutput(parser.format, fmt, **kw) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 000000000000 -r 60d3ee6ab9f1 setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Sat Apr 14 00:42:16 2012 +0200 @@ -0,0 +1,13 @@ +#! /usr/bin/env python + +from distutils.core import setup + +setup( + name = "MoinShare", + description = "Share and receive content updates using MoinMoin", + author = "Paul Boddie", + author_email = "paul@boddie.org.uk", + url = "http://moinmo.in/ParserMarket/MoinShare", + version = "0.1", + py_modules = ["MoinShare"] + ) diff -r 000000000000 -r 60d3ee6ab9f1 tests/test_regions.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_regions.py Sat Apr 14 00:42:16 2012 +0200 @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +from MoinShare import getRegions + +s = """ +Test some shared content... + +{{{#!MoinShare +Hello! + +This is ''testing'' shared content. +}}} + +{{{#!MoinShare format=html + + + + + +
Test some HTML content.This is a table.
+}}} + +Some trailing content. +""" + +regions = getRegions(s) +expected = 2 + +print regions +print +print len(regions) == expected, ": length is", len(regions), "==", expected + +# vim: tabstop=4 expandtab shiftwidth=4