1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - SectionBreakout 4 5 Break sections out of a page, making new pages for each of the sections and 6 replacing them with Include macros. 7 8 @copyright: 2011 Paul Boddie <paul@boddie.org.uk> 9 @license: GNU GPL, see COPYING for details. 10 """ 11 12 Dependencies = ['pages'] 13 14 from MoinMoin.action import ActionBase 15 from MoinMoin.PageEditor import PageEditor 16 from MoinContentSupport import * 17 import re 18 19 # Action class and supporting functions. 20 21 class SectionBreakout(ActionBase, ActionSupport): 22 23 "An action breaking sections out of pages." 24 25 def get_form_html(self, buttons_html): 26 _ = self._ 27 request = self.request 28 page = self.page 29 form = self.get_form() 30 31 level = int(form.get("level", ["2"])[0]) 32 33 # Acquire heading details from the page. 34 35 body = page.get_raw_body() 36 heading_details = getHeadingDetails(body, level, level) 37 38 d = { 39 "buttons_html" : buttons_html, 40 "heading_level_label" : escape(_("Heading level")), 41 "found_headings_label" : escape(_("Headings found in page")), 42 "propagate_categories_label" : escape(_("Propagate categories")), 43 "preview_label" : escape(_("Preview")), 44 "level" : escattr(level), 45 } 46 47 html = u''' 48 <table> 49 <tr> 50 <td class="label">%(heading_level_label)s</td> 51 <td><input type="text" name="level" value="%(level)s" size="2" /></td> 52 </tr> 53 <tr> 54 <td class="label">%(found_headings_label)s</td> 55 <td>''' % d 56 57 for heading, level, span in heading_details: 58 html += "%s<br />" % heading 59 60 html += ''' 61 </td> 62 </tr> 63 <tr> 64 <td class="label">%(propagate_categories_label)s</td> 65 <td class="buttons"><input type="checkbox" name="propagate" value="yes" /></td> 66 </tr> 67 <tr> 68 <td></td> 69 <td class="buttons"><input type="submit" value="%(preview_label)s" />%(buttons_html)s</td> 70 </tr> 71 </table> 72 ''' % d 73 74 return html 75 76 def do_action(self): 77 78 "Create the new event." 79 80 _ = self._ 81 form = self.get_form() 82 83 # A heading level must be provided. 84 85 level = form.get("level", [None])[0] 86 propagate = form.get("propagate", [None])[0] 87 88 if not level: 89 return 0, _("No heading level specified.") 90 91 return self.break_out_headings(int(level), propagate) 92 93 def render_success(self, msg, msgtype=None): 94 95 """ 96 Render neither 'msg' nor 'msgtype' since redirection should occur 97 instead. 98 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 99 """ 100 101 pass 102 103 def break_out_headings(self, level, propagate): 104 105 """ 106 Break out headings at the given 'level' from the current page. If 107 'propagate' is a true value, propagate categories to subpages. 108 """ 109 110 _ = self._ 111 request = self.request 112 page = self.page 113 formatter = request.formatter 114 115 # Acquire all heading details from the page. 116 117 page_body = page.get_raw_body() 118 119 if propagate: 120 categories = getCategoryMembership(page_body) 121 122 regions = [] 123 current_region_start = None 124 125 for heading, found_level, (start, end) in getHeadingDetails(page_body): 126 127 # Upon finding a suitable heading, begin a new region to be broken 128 # out. 129 130 if current_region_start is None and found_level >= level: 131 current_region_start = heading, start 132 133 # Upon finding a higher-level heading, end any open region. 134 135 elif current_region_start is not None and found_level <= level: 136 regions.append(current_region_start + (start,)) 137 138 # For headings at the requested level, open a new region. 139 140 if found_level == level: 141 current_region_start = heading, start 142 else: 143 current_region_start = None 144 145 # End any open region. 146 147 else: 148 if current_region_start is not None: 149 regions.append(current_region_start + (len(page_body),)) 150 151 # Make new pages for each region, rebuilding the current page body. 152 153 retained_regions = [] 154 retained_region_start = 0 155 new_page_names = {} 156 157 for heading, start, end in regions: 158 159 # Combine the page name and the heading to make a subpage. 160 161 new_page_name = "%s/%s" % (page.page_name, heading) 162 163 # Distinguish between pages which use the same heading. 164 165 n = new_page_names.get(new_page_name, 0) 166 if n: 167 new_page_names[new_page_name] = n + 1 168 new_page_name += " (%d)" % (n + 1) 169 else: 170 new_page_names[new_page_name] = n + 1 171 172 # Open the page for editing. 173 174 new_page = PageEditor(request, new_page_name) 175 new_page_body = page_body[start:end] 176 177 if propagate: 178 new_page_categories = getCategoryMembership(new_page_body) 179 180 # Add categories if the parent page has any. 181 182 if new_page_categories != categories: 183 new_page_body += getCategoryDeclaration(categories) 184 185 # Save the new page. 186 187 try: 188 new_page.saveText(new_page_body, 0) 189 except PageEditor.Unchanged: 190 pass 191 192 # Retain the preceding region for the current page. 193 194 retained_regions.append(page_body[retained_region_start:start]) 195 196 # Insert Include macros for the broken out text. 197 198 retained_regions.append("<<Include(%s,,editlink)>>\n" % new_page_name) 199 200 # Start a new region to retain. 201 202 retained_region_start = end 203 204 # Retain any remaining text. 205 206 else: 207 retained_regions.append(page_body[retained_region_start:]) 208 209 # Edit the current page. 210 211 edited_page = PageEditor(request, page.page_name) 212 edited_page_body = "".join(retained_regions) 213 214 if propagate: 215 edited_page_categories = getCategoryMembership(edited_page_body) 216 217 # Add categories if the parent page should have any, but these were 218 # broken out. 219 220 if edited_page_categories != categories: 221 edited_page_body += getCategoryDeclaration(categories) 222 223 # Save the current page. 224 225 edited_page.saveText(edited_page_body, 0) 226 227 # NOTE: Perhaps show a message upon failure. 228 229 request.http_redirect(page.url(request)) 230 return 1, None 231 232 # Action function. 233 234 def execute(pagename, request): 235 SectionBreakout(pagename, request).render() 236 237 # vim: tabstop=4 expandtab shiftwidth=4