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 ActionSupport, getHeadingDetails, escape, escattr 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 regions = [] 112 current_region_start = None 113 114 for heading, found_level, (start, end) in getHeadingDetails(page_body): 115 116 # Upon finding a suitable heading, begin a new region to be broken 117 # out. 118 119 if current_region_start is None and found_level >= level: 120 current_region_start = heading, start 121 122 # Upon finding a higher-level heading, end any open region. 123 124 elif current_region_start is not None and found_level <= level: 125 regions.append(current_region_start + (start,)) 126 127 # For headings at the requested level, open a new region. 128 129 if found_level == level: 130 current_region_start = heading, start 131 else: 132 current_region_start = None 133 134 # End any open region. 135 136 else: 137 if current_region_start is not None: 138 regions.append(current_region_start + (len(page_body),)) 139 140 # Make new pages for each region, rebuilding the current page body. 141 142 retained_regions = [] 143 retained_region_start = 0 144 145 for heading, start, end in regions: 146 147 # Combine the page name and the heading to make a subpage. 148 149 new_page_name = "%s/%s" % (page.page_name, heading) 150 151 # Open the page for editing. 152 153 new_page = PageEditor(request, new_page_name) 154 155 # Save the new version of the page. 156 157 new_page.saveText(page_body[start:end], 0) 158 159 # Retain the preceding region for the current page. 160 161 retained_regions.append(page_body[retained_region_start:start]) 162 163 # Insert Include macros for the broken out text. 164 165 retained_regions.append("<<Include(%s,,editlink)>>\n" % new_page_name) 166 167 # Start a new region to retain. 168 169 retained_region_start = end 170 171 # Retain any remaining text. 172 173 else: 174 retained_regions.append(page_body[retained_region_start:]) 175 176 # Edit the current page. 177 178 edited_page = PageEditor(request, page.page_name) 179 edited_page.saveText("".join(retained_regions), 0) 180 181 # NOTE: Perhaps show a message upon failure. 182 183 request.http_redirect(page.url(request)) 184 return 1, None 185 186 # Action function. 187 188 def execute(pagename, request): 189 SectionBreakout(pagename, request).render() 190 191 # vim: tabstop=4 expandtab shiftwidth=4