diff -ur 1.5b2/Include.py modified/Include.py --- 1.5b2/Include.py 2005-10-28 03:46:38.000000000 +0900 +++ modified/Include.py 2005-11-24 03:09:42.649867300 +0900 @@ -218,7 +218,7 @@ request.redirect(strfile) try: cid = request.makeUniqueID("Include_%s" % wikiutil.quoteWikinameURL(inc_page.page_name)) - inc_page.send_page(request, content_only=1, content_id=cid) + inc_page.send_page(request, content_only=1, content_id=cid, do_cache=False) result.append(strfile.getvalue()) finally: request.redirect() diff -ur 1.5b2/multiconfig.py modified/multiconfig.py --- 1.5b2/multiconfig.py 2005-10-30 20:22:58.000000000 +0900 +++ modified/multiconfig.py 2005-11-23 02:56:50.156250000 +0900 @@ -290,6 +290,7 @@ show_hosts = 1 show_interwiki = 1 show_section_numbers = 0 + allow_section_edit = 1 show_timings = 0 show_version = 0 siteid = 'default' diff -ur 1.5b2/PageEditor.py modified/PageEditor.py --- 1.5b2/PageEditor.py 2005-11-06 06:28:50.000000000 +0900 +++ modified/PageEditor.py 2005-11-24 10:35:22.009242300 +0900 @@ -135,7 +135,28 @@ edit_lock_message = None preview = kw.get('preview', None) staytop = kw.get('staytop', 0) + + # for section editing + issectionedit = kw.get('issectionedit', 1) + pagetext = kw.get('pagetext', None) + startline = int(form.get('startline', ['0'])[0]) + endline = int(form.get('endline', ['0'])[0]) + srev = int(form.get('srev', ['0'])[0]) + + if startline or endline: + if not startline: + startline = 1 + + if not endline: + endline = -1 + else: + issectionedit = 0 + if issectionedit: + # need to add config + self._allow_section_edit = self.cfg.allow_section_edit + # self._allow_section_edit = 1 + from MoinMoin.formatter.text_html import Formatter self.request.formatter = Formatter(self.request, store_pagelinks=1) @@ -174,7 +195,10 @@ title = _('Edit "%(pagename)s"') else: title = _('Preview of "%(pagename)s"') - self.set_raw_body(preview, modified=1) + if issectionedit and pagetext is not None: + self.set_raw_body(pagetext, modified=1) + else: + self.set_raw_body(preview, modified=1) # send header stuff lock_timeout = self.lock.timeout / 60 @@ -214,9 +238,19 @@ # We don't show preview when in conflict preview = None + # no section-editing any more + if issectionedit: + conflict_msg = u'%s %s' % (conflict_msg, _('Section editing is canceled.')) + issectionedit = 0 + elif self.exists(): # revision of existing page rev = self.current_rev() + + if issectionedit and preview is None: + if not (srev and srev == rev): + conflict_msg = u'%s %s' % (_('Section editing is canceled.'), _('Someone else updated this page. You are editing the updated revision.')) + issectionedit = 0 else: # page creation rev = 0 @@ -273,6 +307,12 @@ # Generate default content for new pages if not raw_body: raw_body = _('Describe %s here.') % (self.page_name,) + elif issectionedit: + # for section editing + if pagetext is not None: + raw_body = preview + else: + raw_body = self.fetchsection(raw_body, startline, endline) # send form self.request.write('
' % ( @@ -290,6 +330,11 @@ # Send revision of the page our edit is based on self.request.write('' % (rev,)) + # Send section startline and endline for section-editing + if issectionedit: + self.request.write('' % startline) + self.request.write('' % endline) + # Save backto in a hidden input backto = form.get('backto', [None])[0] if backto: @@ -391,6 +436,9 @@ badwords_re = None if preview is not None: + if issectionedit: + self.set_raw_body(preview) + if SpellCheck and ( form.has_key('button_spellcheck') or form.has_key('button_newwords')): @@ -414,7 +462,12 @@ content_id = 'previewbelow' else: content_id = 'preview' - self.send_page(self.request, content_id=content_id, content_only=1, + + if issectionedit: + self.send_page(self.request, content_id=content_id, content_only=1, + hilite_re=badwords_re, do_cache=False) + else: + self.send_page(self.request, content_id=content_id, content_only=1, hilite_re=badwords_re) self.request.write(self.request.formatter.endContent()) @@ -860,7 +913,7 @@ if newtext==saved_page.get_raw_body(): msg = _("You already saved this page!") return msg - + msg = _("""Sorry, someone else saved the page while you edited it. Please do the following: Use the back button of your browser, and cut&paste @@ -926,7 +979,17 @@ self.lock.release(force=not msg) # XXX does "not msg" make any sense? return msg - + + def fetchsection(self, pagetext, startline, endline): + + pagetext = pagetext.split('\n') + if endline == -1: + sectiontext = u'\n'.join(pagetext[startline-1:]) + else: + sectiontext = u'\n'.join(pagetext[startline-1:endline]) + + return sectiontext + class PageLock: """ diff -ur 1.5b2/PageGraphicalEditor.py modified/PageGraphicalEditor.py --- 1.5b2/PageGraphicalEditor.py 2005-11-06 06:35:56.000000000 +0900 +++ modified/PageGraphicalEditor.py 2005-11-24 09:50:32.149867300 +0900 @@ -63,6 +63,27 @@ edit_lock_message = None preview = kw.get('preview', None) staytop = kw.get('staytop', 0) + + # for section editing + issectionedit = kw.get('issectionedit', 1) + pagetext = kw.get('pagetext', None) + startline = int(form.get('startline', ['0'])[0]) + endline = int(form.get('endline', ['0'])[0]) + srev = int(form.get('srev', ['0'])[0]) + + if startline or endline: + if not startline: + startline = 1 + + if not endline: + endline = -1 + else: + issectionedit = 0 + + if issectionedit: + # need to add config + self._allow_section_edit = self.cfg.allow_section_edit + # self._allow_section_edit = 1 # check edit permissions if not self.request.user.may.write(self.page_name): @@ -94,7 +115,10 @@ title = _('Edit "%(pagename)s"') else: title = _('Preview of "%(pagename)s"') - self.set_raw_body(preview, modified=1) + if issectionedit and pagetext is not None: + self.set_raw_body(pagetext, modified=1) + else: + self.set_raw_body(preview, modified=1) # send header stuff lock_timeout = self.lock.timeout / 60 @@ -134,9 +158,19 @@ # We don't show preview when in conflict preview = None + # no section-editing any more + if issectionedit: + conflict_msg = u'%s %s' % (conflict_msg, _('Section editing is canceled.')) + issectionedit = 0 + elif self.exists(): # revision of existing page rev = self.current_rev() + + if issectionedit and preview is None: + if not (srev and srev == rev): + conflict_msg = u'%s %s' % (_('Section editing is canceled.'), _('Someone else updated this page. You are editing the updated revision.')) + issectionedit = 0 else: # page creation rev = 0 @@ -193,13 +227,19 @@ # Generate default content for new pages if not raw_body: raw_body = _('Describe %s here.') % (self.page_name,) - + elif issectionedit: + # for section editing + if pagetext is not None: + raw_body = preview + else: + raw_body = self.fetchsection(raw_body, startline, endline) + # send form self.request.write('' % ( self.request.getScriptname(), wikiutil.quoteWikinameURL(self.page_name), )) - + # yet another weird workaround for broken IE6 (it expands the text # editor area to the right after you begin to type...). IE sucks... # http://fplanque.net/2003/Articles/iecsstextarea/ @@ -210,6 +250,11 @@ # Send revision of the page our edit is based on self.request.write('' % (rev,)) + # Send section startline and endline for section-editing + if issectionedit: + self.request.write('' % startline) + self.request.write('' % endline) + # Save backto in a hidden input backto = form.get('backto', [None])[0] if backto: @@ -328,9 +373,12 @@ }) self.request.write("

") - + badwords_re = None if preview is not None: + if issectionedit: + self.set_raw_body(preview) + if SpellCheck and ( form.has_key('button_spellcheck') or form.has_key('button_newwords')): @@ -345,10 +393,16 @@ content_id = 'previewbelow' else: content_id = 'preview' - self.send_page(self.request, content_id=content_id, content_only=1, + + if issectionedit: + self.send_page(self.request, content_id=content_id, content_only=1, + hilite_re=badwords_re, do_cache=False) + else: + self.send_page(self.request, content_id=content_id, content_only=1, hilite_re=badwords_re) self.request.write(self.request.formatter.endContent()) # end content div self.request.theme.emit_custom_html(self.cfg.page_footer1) self.request.theme.emit_custom_html(self.cfg.page_footer2) + diff -ur 1.5b2/text_html.py modified/text_html.py --- 1.5b2/text_html.py 2005-10-31 08:39:10.000000000 +0900 +++ modified/text_html.py 2005-11-24 11:11:23.384242300 +0900 @@ -39,6 +39,16 @@ self._is_included = kw.get('is_included',False) self.request = request self.cfg = request.cfg + + # for section editing + self._allow_section_edit = None + if not hasattr(request, 'sectionindex'): + request.sectionindex = 0 + + self.sectionstack = [] + self.sectionpool = {} + self.sectionlastdepth = 0 + self.lineno = 0 if not hasattr(request, '_fmt_hd_counters'): request._fmt_hd_counters = [] @@ -285,6 +295,7 @@ return '' % (id, ) # do not add a \n here, it breaks pre sections with line_anchordef def line_anchordef(self, lineno): + self.lineno = lineno return self.anchordef("line-%d" % lineno) def anchorlink(self, on, name='', id=None): @@ -689,6 +700,21 @@ if not self._base_depth: self._base_depth = depth + # section editing configuration + if self._allow_section_edit is None: + # need to add config + self._allow_section_edit = self.cfg.allow_section_edit + # self._allow_section_edit = 1 + sectionediting = self.request.getPragma('section-edit', '').lower() + if sectionediting in ['off']: + self._allow_section_edit = 0 + elif sectionediting in ['on']: + self._allow_section_edit = 1 + + if self._allow_section_edit: + if not self.request.user.may.write(self.page.page_name): + self._allow_section_edit = 0 + count_depth = max(depth - (self._base_depth - 1), 1) # check numbering, possibly changing the default @@ -707,7 +733,32 @@ # closing tag, with empty line after, to make source more readable if not on: - return self.close('h%d' % heading_depth) + '\n' + result = self.close('h%d' % heading_depth) + + sectionscript = '' + if self._allow_section_edit: + + self.request.sectionindex += 1 + sectionindex = self.request.sectionindex + sectionscript = self.savesectioninfor(sectionindex, depth, self.lineno) + + attr = 'id="sectionedit%d"' % sectionindex + + backto = u'' + if self._is_included and hasattr(self.request, "_Include_backto"): + backto = u'&backto=%s' % wikiutil.quoteWikinameURL(self.request._Include_backto) + + sectioneditpage = u'%s/%s' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.page.page_name)) + srev = self.page.current_rev() + querystring = u'%s?action=edit%s&srev=%d&startline=%d' % (sectioneditpage, backto, srev, self.lineno) + + result = ('%s%s%s%s' % + (self.url(1, querystring, unescaped=1, title='Edit this section', attrs=attr), + self.icon('edit'), + self.url(0), + result)) + + return ' %s%s' % (result, sectionscript) # create section number number = '' @@ -840,6 +891,53 @@ return self.open(tag, newline=1, attr=attrs) return self.close(tag) + def savesectioninfor(self, index, depth, lineno, save=1): + # store section information + section = {} + sectionscriptlist = [] + sectionscript = u'document.getElementById("sectionedit%d").href += "&endline=%d";' + scriptresult = '' + + lastdepth = self.sectionlastdepth + sectionindex = index + + if lastdepth >= depth: + while 1: + if len(self.sectionstack): + lastsection = self.sectionstack.pop() + lastdepth = lastsection['depth'] + if lastdepth >= depth: + self.sectionpool[lastsection['index']]['endlineno'] = lineno - 1 + sectionscriptlist.append(sectionscript % (lastsection['index'], lineno - 1)) + else: + self.sectionstack.append(lastsection) + break + else: + break + + if save: + section['index'] = sectionindex + section['startlineno'] = lineno + section['depth'] = depth + section['endlineno'] = -1 + self.sectionlastdepth = depth + self.sectionpool[sectionindex] = section + self.sectionstack.append(section) + + if len(sectionscriptlist) > 0: + + scriptresult = u""" + +""" % u'\n'.join(sectionscriptlist) + + return scriptresult + + + def escapedText(self, text): return wikiutil.escape(text) diff -ur 1.5b2/wikiaction.py modified/wikiaction.py --- 1.5b2/wikiaction.py 2005-10-23 21:50:50.000000000 +0900 +++ modified/wikiaction.py 2005-11-24 09:47:28.196742300 +0900 @@ -563,10 +563,6 @@ from MoinMoin.PageEditor import PageEditor pg = PageEditor(request, pagename) - # Edit was canceled - if request.form.has_key('button_cancel'): - pg.sendCancel(savetext, rev) - return # is invoked without savetext start editing if savetext is None: @@ -577,11 +573,39 @@ if lasteditor == 'gui': from MoinMoin.converter.text_html_text_x_moin import convert savetext = convert(request, pagename, savetext) # XXX error handling + + # section editing + startline = int(request.form.get('startline', ['0'])[0]) + endline = int(request.form.get('endline', ['0'])[0]) + + if startline or endline: + issectionedit = 1 + + if not startline: + startline = 1 + + if not endline: + endline = -1 + + else: + issectionedit = 0 + + if issectionedit: + savetext = pg.normalizeText(savetext, stripspaces=rstrip) + sectiontext = savetext + savetext = mergesection(pg.get_raw_body(), savetext, startline, endline) + + + # Edit was canceled + if request.form.has_key('button_cancel'): + pg.sendCancel(savetext, rev) + return # IMPORTANT: normalize text from the form. This should be done in # one place before we manipulate the text. - savetext = pg.normalizeText(savetext, stripspaces=rstrip) - + if not issectionedit: + savetext = pg.normalizeText(savetext, stripspaces=rstrip) + # Add category # TODO: this code does not work with extended links, and is doing @@ -630,11 +654,17 @@ if (request.form.has_key('button_preview') or request.form.has_key('button_spellcheck') or request.form.has_key('button_newwords')): - pg.sendEditor(preview=savetext, comment=comment) + if issectionedit: + pg.sendEditor(preview=sectiontext, comment=comment, pagetext=savetext) + else: + pg.sendEditor(preview=savetext, comment=comment) # Preview with mode switch elif request.form.has_key('button_switch'): - pg.sendEditor(preview=savetext, comment=comment, staytop=1) + if issectionedit: + pg.sendEditor(preview=sectiontext, comment=comment, staytop=1, pagetext=savetext) + else: + pg.sendEditor(preview=savetext, comment=comment, staytop=1) # Save new text else: @@ -655,7 +685,10 @@ querystr='action=diff&rev=%d' % rev) } # We don't send preview when we do merge conflict - pg.sendEditor(msg=conflict_msg, comment=comment) + if issectionedit: + conflict_msg = u'%s %s' % (conflict_msg, _('Section editing is canceled.')) + + pg.sendEditor(msg=conflict_msg, comment=comment, issectionedit=0) return else: savemsg = conflict_msg @@ -949,6 +982,15 @@ return handler - - +def mergesection(pagetext, newsectiontext, startline, endline): + + pagetext = pagetext.split('\n') + + prevtext = u'%s\n' % u'\n'.join(pagetext[:startline-1]) + if endline == -1: + nexttext = '' + else: + nexttext = u'\n%s' % u'\n'.join(pagetext[endline:]) + + return u'%s%s%s' % (prevtext, newsectiontext, nexttext)