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 "preview_label" : escape(_("Preview")), 43 "level" : escattr(level), 44 } 45 46 html = u''' 47 <table> 48 <tr> 49 <td class="label">%(heading_level_label)s</td> 50 <td><input type="text" name="level" value="%(level)s" size="2" /></td> 51 </tr> 52 <tr> 53 <td class="label">%(found_headings_label)s</td> 54 <td>''' % d 55 56 for heading, level, span in heading_details: 57 html += "%s<br />" % heading 58 59 html += ''' 60 </td> 61 </tr> 62 <tr> 63 <td></td> 64 <td class="buttons"><input type="submit" value="%(preview_label)s" />%(buttons_html)s</td> 65 </tr> 66 </table> 67 ''' % d 68 69 return html 70 71 def do_action(self): 72 73 "Create the new event." 74 75 _ = self._ 76 form = self.get_form() 77 78 # A heading level must be provided. 79 80 level = form.get("level", [None])[0] 81 82 if not level: 83 return 0, _("No heading level specified.") 84 85 return self.break_out_headings(int(level)) 86 87 def render_success(self, msg, msgtype=None): 88 89 """ 90 Render neither 'msg' nor 'msgtype' since redirection should occur 91 instead. 92 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 93 """ 94 95 pass 96 97 def break_out_headings(self, level): 98 99 """ 100 Break out headings at the given 'level' from the current page. 101 """ 102 103 _ = self._ 104 request = self.request 105 page = self.page 106 formatter = request.formatter 107 108 # Acquire all heading details from the page. 109 110 page_body = page.get_raw_body() 111 categories = getCategoryMembership(page_body) 112 113 regions = [] 114 current_region_start = None 115 116 for heading, found_level, (start, end) in getHeadingDetails(page_body): 117 118 # Upon finding a suitable heading, begin a new region to be broken 119 # out. 120 121 if current_region_start is None and found_level >= level: 122 current_region_start = heading, start 123 124 # Upon finding a higher-level heading, end any open region. 125 126 elif current_region_start is not None and found_level <= level: 127 regions.append(current_region_start + (start,)) 128 129 # For headings at the requested level, open a new region. 130 131 if found_level == level: 132 current_region_start = heading, start 133 else: 134 current_region_start = None 135 136 # End any open region. 137 138 else: 139 if current_region_start is not None: 140 regions.append(current_region_start + (len(page_body),)) 141 142 # Make new pages for each region, rebuilding the current page body. 143 144 retained_regions = [] 145 retained_region_start = 0 146 new_page_names = {} 147 148 for heading, start, end in regions: 149 150 # Combine the page name and the heading to make a subpage. 151 152 new_page_name = "%s/%s" % (page.page_name, heading) 153 154 # Distinguish between pages which use the same heading. 155 156 n = new_page_names.get(new_page_name, 0) 157 if n: 158 new_page_names[new_page_name] = n + 1 159 new_page_name += " (%d)" % (n + 1) 160 else: 161 new_page_names[new_page_name] = n + 1 162 163 # Open the page for editing. 164 165 new_page = PageEditor(request, new_page_name) 166 new_page_body = page_body[start:end] 167 new_page_categories = getCategoryMembership(new_page_body) 168 169 # Add categories if the parent page has any. 170 171 if new_page_categories != categories: 172 new_page_body += getCategoryDeclaration(categories) 173 174 # Save the new page. 175 176 new_page.saveText(new_page_body, 0) 177 178 # Retain the preceding region for the current page. 179 180 retained_regions.append(page_body[retained_region_start:start]) 181 182 # Insert Include macros for the broken out text. 183 184 retained_regions.append("<<Include(%s,,editlink)>>\n" % new_page_name) 185 186 # Start a new region to retain. 187 188 retained_region_start = end 189 190 # Retain any remaining text. 191 192 else: 193 retained_regions.append(page_body[retained_region_start:]) 194 195 # Edit the current page. 196 197 edited_page = PageEditor(request, page.page_name) 198 edited_page_body = "".join(retained_regions) 199 edited_page_categories = getCategoryMembership(edited_page_body) 200 201 # Add categories if the parent page should have any, but these were 202 # broken out. 203 204 if edited_page_categories != categories: 205 edited_page_body += getCategoryDeclaration(categories) 206 207 # Save the current page. 208 209 edited_page.saveText(edited_page_body, 0) 210 211 # NOTE: Perhaps show a message upon failure. 212 213 request.http_redirect(page.url(request)) 214 return 1, None 215 216 # Action function. 217 218 def execute(pagename, request): 219 SectionBreakout(pagename, request).render() 220 221 # vim: tabstop=4 expandtab shiftwidth=4