1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - MoinContentSupport library 4 5 @copyright: 2008, 2009, 2010, 2011 by Paul Boddie <paul@boddie.org.uk> 6 @copyright: 2000-2004 Juergen Hermann <jh@web.de>, 7 2005-2008 MoinMoin:ThomasWaldmann. 8 @license: GNU GPL (v2 or later), see COPYING.txt for details. 9 """ 10 11 from MoinMoin.wikiutil import escape 12 import re 13 14 __version__ = "0.1" 15 16 # Regular expressions. 17 # NOTE: These overlap with ImprovedMoinSearch and EventAggregator. 18 19 heading_regexp = re.compile(r"^(?P<level>=+)\s*(?P<heading>.*?)\s*(?P=level)$", re.UNICODE | re.MULTILINE) 20 21 category_membership_str = ur"^\s*(?:(Category\S+)(?:\s+(Category\S+))*)\s*$" 22 category_membership_regexp = re.compile(category_membership_str, re.MULTILINE | re.UNICODE) 23 category_declarations_regexp = re.compile("^----$\s*" + category_membership_str, re.MULTILINE | re.UNICODE) 24 25 def getHeadingDetails(body, min_level=None, max_level=None): 26 27 """ 28 Return heading details from the given 'body' for headings with the given 29 'min_level' to 'max_level' range. Specifying None or omitting 'max_level' or 30 'min_level' removes the appropriate constraint on the range. 31 32 A list of tuples containing the heading, the level, and the span (the start 33 offset and the end offset as a tuple) is returned. 34 """ 35 36 headings = [] 37 38 for match in heading_regexp.finditer(body): 39 level = len(match.group("level")) 40 41 if (min_level is None or min_level <= level) and \ 42 (max_level is None or level <= max_level): 43 44 headings.append((match.group("heading"), level, match.span())) 45 46 return headings 47 48 def getCategoryMembership(body): 49 50 "From the given 'body', return the categories the page belongs to." 51 52 match = category_membership_regexp.search(body) 53 if match: 54 return [x for x in match.groups() if x] 55 else: 56 return [] 57 58 def getCategoryDeclarations(body): 59 60 """ 61 From the given 'body', return the category declaration sections in the page 62 in the form of a list of tuples, each containing a list of categories, the 63 start of the declaration region and the end of the region. 64 """ 65 66 return [([x for x in match.groups() if x], match.span()) for match in category_declarations_regexp.finditer(body)] 67 68 def makeCategoryDeclaration(categories): 69 70 "Return a category declaration string for the given 'categories'." 71 72 return "\n----\n%s\n" % " ".join(categories) 73 74 # Utility classes and associated functions. 75 # NOTE: These are a subset of EventAggregatorSupport. 76 77 class Form: 78 79 """ 80 A wrapper preserving MoinMoin 1.8.x (and earlier) behaviour in a 1.9.x 81 environment. 82 """ 83 84 def __init__(self, form): 85 self.form = form 86 87 def get(self, name, default=None): 88 values = self.form.getlist(name) 89 if not values: 90 return default 91 else: 92 return values 93 94 def __getitem__(self, name): 95 return self.form.getlist(name) 96 97 class ActionSupport: 98 99 """ 100 Work around disruptive MoinMoin changes in 1.9, and also provide useful 101 convenience methods. 102 """ 103 104 def get_form(self): 105 return get_form(self.request) 106 107 def get_form(request): 108 109 "Work around disruptive MoinMoin changes in 1.9." 110 111 if hasattr(request, "values"): 112 return Form(request.values) 113 else: 114 return request.form 115 116 class send_headers: 117 118 """ 119 A wrapper to preserve MoinMoin 1.8.x (and earlier) request behaviour in a 120 1.9.x environment. 121 """ 122 123 def __init__(self, request): 124 self.request = request 125 126 def __call__(self, headers): 127 for header in headers: 128 parts = header.split(":") 129 self.request.headers.add(parts[0], ":".join(parts[1:])) 130 131 def escattr(s): 132 return escape(s, 1) 133 134 # vim: tabstop=4 expandtab shiftwidth=4