Details
- Applies to
- Moin 1.8
- Purpose
Add multiple templates support to NewPage Macro
- Description
The orignal NewPage macro only support one template. If the user want to create a page from multiple templates, user has to write multiple NewPage macro. Tedious and not neatly.
Patch
1 # Add a dropdown select list for NewPage macro to support multiple template selection.
2 # Pass categories to NewPage macro, and categories append at the end of new page.
3
4 diff -r 6419f0986299 MoinMoin/PageEditor.py
5 --- a/MoinMoin/PageEditor.py Fri Nov 21 23:12:33 2008 +0800
6 +++ b/MoinMoin/PageEditor.py Sat Nov 22 15:07:55 2008 +0800
7 @@ -20,6 +20,7 @@
8
9
10 from MoinMoin import caching, config, wikiutil, error
11 +from MoinMoin import wikiutil2
12 from MoinMoin.Page import Page
13 from MoinMoin.widget import html
14 from MoinMoin.widget.dialog import Status
15 @@ -426,6 +427,9 @@
16 lang = self.pi.get('language', request.cfg.language_default)
17
18 request.write("<p>")
19 + category = form.get('category',[None])[0] or kw.get('category', None)
20 + if category:
21 + raw_body = wikiutil2.append_category(request, raw_body, category)
22 request.write(
23 u'''\
24 <textarea id="editor-textarea" name="savetext" lang="%(lang)s" dir="%(dir)s" rows="%(rows)d" cols="80"
25 diff -r 6419f0986299 MoinMoin/action/edit.py
26 --- a/MoinMoin/action/edit.py Fri Nov 21 23:12:33 2008 +0800
27 +++ b/MoinMoin/action/edit.py Sat Nov 22 15:07:55 2008 +0800
28 @@ -8,7 +8,7 @@
29 2006 MoinMoin:ThomasWaldmann
30 @license: GNU GPL, see COPYING for details.
31 """
32 -from MoinMoin import wikiutil
33 +from MoinMoin import wikiutil, wikiutil2
34 from MoinMoin.Page import Page
35
36 def execute(pagename, request):
37 @@ -122,30 +122,7 @@
38 # markup.
39
40 if category and category != _('<No addition>'): # opera 8.5 needs this
41 - # strip trailing whitespace
42 - savetext = savetext.rstrip()
43 -
44 - # Add category separator if last non-empty line contains
45 - # non-categories.
46 - lines = [line for line in savetext.splitlines() if line]
47 - if lines:
48 -
49 - import re
50 - p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
51 - p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
52 - categories = map( lambda x: p_strip.search(x).groups()[0],
53 - p_split.findall(lines[-1]))
54 -
55 - if categories:
56 - confirmed = wikiutil.filterCategoryPages(request, categories)
57 - if len(confirmed) < len(categories):
58 - # This was not a categories line, add separator
59 - savetext += u'\n----\n'
60 -
61 - # Add new category
62 - if savetext and savetext[-1] != u'\n':
63 - savetext += ' '
64 - savetext += category + u'\n' # Should end with newline!
65 + savetext = wikiutil2.append_category(request, savetext, category)
66
67 # Preview, spellcheck or spellcheck add new words
68 if ('button_preview' in request.form or
69 diff -r 6419f0986299 MoinMoin/action/newpage.py
70 --- a/MoinMoin/action/newpage.py Fri Nov 21 23:12:33 2008 +0800
71 +++ b/MoinMoin/action/newpage.py Sat Nov 22 15:07:55 2008 +0800
72 @@ -22,7 +22,51 @@
73 self.pagename = self.request.form.get('pagename', [None])[0]
74 self.nametemplate = self.request.form.get('nametemplate', ['%s'])[0]
75 self.nametemplate = self.nametemplate.replace('\x00', '')
76 + self.parent = self.request.form.get('parent', [''])[0]
77 + self.template = self.request.form.get('template', [''])[0]
78 + self.category = self.request.form.get('category', [None])[0]
79 + if ',' in self.template:
80 + arg_kw = self.parse_combined_template(self.template)
81 + self.template = arg_kw.get('template', "")
82 + self.parent = arg_kw.get('parent') or self.parent
83 + self.nametemplate = arg_kw.get('nametemplate') or self.nametemplate
84 + category = arg_kw.get('category', "")
85 + if self.category and category:
86 + self.category = ','.join([self.category, category])
87 + else:
88 + self.category = self.category or category
89
90 + def parse_combined_template(self, template):
91 + kw = {'template':'',
92 + 'parent':'',
93 + 'nametemplate':'',
94 + 'category':'',
95 + }
96 + if template and ',' in template:
97 + for item in template.split(','):
98 + item = item.strip()
99 + # check if item is template
100 + if not kw['template'] and self.request.cfg.cache.page_template_regex.search(item):
101 + kw['template'] = item
102 + # check if item is category
103 + elif self.request.cfg.cache.page_category_regexact.search(item):
104 + if kw['category']:
105 + kw['category'] = ','.join([kw['category'], item])
106 + else:
107 + kw['category'] = item
108 + # then item is parent or nametemplate
109 + elif not kw['parent']:
110 + kw['parent'] = item
111 + elif not kw['nametemplate']:
112 + kw['nametemplate'] = item
113 + else:
114 + # ignore bad parameters
115 + pass
116 + else:
117 + kw['template'] = template
118 +
119 + return kw
120 +
121 def checkAndCombineArguments(self):
122 """ Check arguments in form, return error msg
123
124 @@ -82,13 +126,14 @@
125 pagename = self.pagename
126 query = {'action': 'edit', 'backto': self.referrer}
127
128 - template = self.request.form.get('template', [''])[0]
129 - if template:
130 - query['template'] = template
131 + if self.template:
132 + query['template'] = self.template
133 +
134 + if self.category:
135 + query['category'] = self.category
136
137 - parent = self.request.form.get('parent', [''])[0]
138 - if parent:
139 - pagename = "%s/%s" % (parent, pagename)
140 + if self.parent:
141 + pagename = "%s/%s" % (self.parent, pagename)
142
143 url = Page(self.request, pagename).url(self.request, query)
144 self.request.http_redirect(url)
145 diff -r 6419f0986299 MoinMoin/macro/NewPage.py
146 --- a/MoinMoin/macro/NewPage.py Fri Nov 21 23:12:33 2008 +0800
147 +++ b/MoinMoin/macro/NewPage.py Sat Nov 22 15:07:55 2008 +0800
148 @@ -25,7 +25,7 @@
149
150 Usage:
151
152 - <<NewPage(template, buttonLabel, parentPage)>>
153 + <<NewPage(template, buttonLabel, parentPage, name_template=u"%s", type=u"select", layout=u"", category=u"")>>
154
155 Examples:
156
157 @@ -39,14 +39,37 @@
158 Create an input field with button labeled 'Create New
159 Bug'. The new page will use the BugTemplate template,
160 and create the page as a subpage of MoinMoinBugs.
161 +
162 + <<NewPage({u"AbcTemplate":u"Abc",u"XyzTemplate":u"Xyz"},
163 + Create,Meetings,%Y-%m-%d_%s, category=u"CategoryX,CategoryY")>>
164 +
165 + User can choose template from a drop down select box.
166 + New page name will have the date at the beginning.
167 + CategoryX and CategoryY will append at the end of the page.
168 +
169 + <<NewPage({u"AbcTemplate,CategoryX":u"Abc",u"XyzTemplate,CategoryY":u"Xyz",u"XyzTemplate,CategoryY,CategoryZ":u"Xyz2"},
170 + Create,Meetings,%Y-%m-%d_%s)>>
171 +
172 + User can choose template from a drop down select box.
173 + New page name will have the date at the beginning.
174 + CategoryX, CategoryY, or CategoryZ will append at the end of the page.
175 """
176
177 def __init__(self, macro, template=u'', button_label=u'',
178 - parent_page=u'', name_template=u'%s'):
179 + parent_page=u'', name_template=u'%s', type=u'select', layout=u'', category=u''):
180 self.macro = macro
181 self.request = macro.request
182 self.formatter = macro.formatter
183 - self.template = template
184 + if isinstance(template, dict):
185 + self.template = []
186 + for k,v in template.iteritems():
187 + self.template.append([v,k])
188 + self.template = sorted(self.template)
189 + self.template = [ (item[1], item[0]) for item in self.template ]
190 + else:
191 + self.template = template
192 + self.type = type
193 + self.layout = layout
194 _ = self.request.getText
195 if button_label:
196 # Try to get a translation, this will probably not work in
197 @@ -66,6 +89,7 @@
198 else:
199 self.parent = parent_page
200 self.nametemplate = name_template
201 + self.category = category
202
203 def renderInPage(self):
204 """ Render macro in page context
205 @@ -77,7 +101,16 @@
206 _ = self.request.getText
207
208 requires_input = '%s' in self.nametemplate
209 -
210 + if not self.layout:
211 + self.layout = """
212 +<table class="borderless">
213 + <tr>
214 + <td>""" + _("Input title: ") + """</td><td>%(input)s</td></tr>
215 + <tr>
216 + <td>""" + _("Select template: ") + """</td><td>%(select)s</td></tr>
217 + <tr><td colspan="2" align="right">%(button)s</td></tr>
218 +</table>
219 +"""
220
221 # TODO: better abstract this using the formatter
222 # OSSXP: self.request.page.page_name and self.formatter.page.page_name may different,
223 @@ -91,26 +124,82 @@
224 except:
225 self.parent = self.formatter.page.page_name
226
227 - html = [
228 + header = [
229 u'<form class="macro" method="POST" action="%s/%s"><div>' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.formatter.page.page_name)),
230 u'<input type="hidden" name="action" value="newpage">',
231 u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(self.parent, 1),
232 - u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1),
233 + u'<input type="hidden" name="category" value="%s">' % wikiutil.escape(self.category, 1),
234 u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(self.nametemplate, 1),
235 ]
236 + header = '\n'.join(header)
237 + footer = u'</div></form>'
238 + button = u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1)
239 +
240 + select = u''
241 + if self.template:
242 + if isinstance(self.template, basestring):
243 + select = u''
244 + header += u'\n<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1)
245 + elif isinstance(self.template, (list,tuple)):
246 + select = []
247 + if self.type == "select":
248 + select.append(u'<select name="template" size="0">')
249 + for item in self.template:
250 + if isinstance(item, basestring):
251 + k=item
252 + v=item
253 + else:
254 + k=item[0]
255 + v=item[1]
256 + if self.type == "select":
257 + select.append(u'<option value="%(key)s" label="%(value)s">%(value)s</option>' % \
258 + {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
259 + else: # type == radio
260 + select.append(u'<input type="radio" name="template" value="%(key)s">%(value)s' % \
261 + {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
262 + if self.type == "select":
263 + select.append(u'</select>')
264 + select = '\n'.join(select)
265 + if requires_input:
266 + input = u'<input type="text" name="pagename" size="30">'
267 + else:
268 + input = u''
269 +
270 + if input and select and self.layout:
271 + html = '\n'.join([header,
272 + self.layout % {'button': button, 'select':select, 'input':input},
273 + footer])
274 + else:
275 + html = '\n'.join([header, select, input, button,footer])
276
277 - if requires_input:
278 - html += [
279 - u'<input type="text" name="pagename" size="30">',
280 - ]
281 - html += [
282 - u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1),
283 - u'</div></form>',
284 - ]
285 - return self.formatter.rawHTML('\n'.join(html))
286 + return self.formatter.rawHTML(html)
287
288 -def macro_NewPage(macro, template=u'', button_label=u'',
289 - parent_page=u'', name_template=u'%s'):
290 +
291 +def execute(macro, args):
292 """ Temporary glue code to use with moin current macro system """
293 - return NewPage(macro, template, button_label, parent_page, name_template).renderInPage()
294 + request = macro.request
295 + import re
296 + pattern = re.compile(ur"""
297 +^(?P<template>
298 + \[.*?\] # list
299 + |
300 + \(.*?\) # tuple
301 + |
302 + \{.*?\} # dict
303 + |
304 + (?P<mark>"').*?(?P=mark) # string with mark
305 + |
306 + [^,]* # string without mark
307 +),?(?P<args>.*)$ # others arguments
308 +""", re.UNICODE|re.VERBOSE)
309 + template = ""
310 + if args:
311 + match = pattern.search(args)
312 + if match:
313 + template = match.group('template')
314 + args = match.group('args')
315 + if template:
316 + if template[0] in '[({\'"':
317 + template = eval(template)
318
319 + return wikiutil.invoke_extension_function(request, NewPage, args, fixed_args=[macro, template]).renderInPage()
320 diff -r 6419f0986299 MoinMoin/wikiutil2.py
321 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
322 +++ b/MoinMoin/wikiutil2.py Sat Nov 22 15:07:55 2008 +0800
323 @@ -0,0 +1,68 @@
324 +# -*- coding: utf-8 -*-
325 +"""
326 + MoinMoin - Wiki Extra Utility Functions
327 +
328 + @copyright: 2008 Jiang Xin <worldhello.net@gmail.com>
329 + @license: GNU GPL, see COPYING for details.
330 +"""
331 +
332 +import re
333 +from MoinMoin import wikiutil
334 +
335 +from MoinMoin import log
336 +logging = log.getLogger(__name__)
337 +
338 +
339 +def append_category(request, raw_body, category):
340 + """
341 + Append category at the end of raw_body
342 + """
343 + _ = request.getText
344 +
345 + # user can input multiple categories, separate by ';'
346 + categorylist = []
347 +
348 + if isinstance(category, (list,tuple)):
349 + categorylist = category
350 + elif isinstance(category, basestring):
351 + for cat in category.split(','):
352 + if cat.startswith("[["):
353 + cat = cat[2:-2]
354 + if request.cfg.cache.page_category_regexact.search(cat):
355 + if cat not in categorylist:
356 + categorylist.append(cat)
357 +
358 + # no valid category, return raw_body
359 + if not categorylist or not raw_body:
360 + return raw_body
361 +
362 + # strip trailing whitespace
363 + raw_body = raw_body.rstrip()
364 +
365 + lines = [line for line in raw_body.splitlines() if line]
366 + p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
367 + p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
368 + categories = map( lambda x: p_strip.search(x).groups()[0],
369 + p_split.findall(lines[-1]))
370 + if categories:
371 + confirmed = wikiutil.filterCategoryPages(request, categories)
372 + if len(confirmed) < len(categories):
373 + # This was not a categories line, add separator
374 + categories = []
375 +
376 + # Add category separator if last non-empty line contains non-categories.
377 + if not categories:
378 + raw_body += u'\n\n----\n'
379 +
380 + for cat in categorylist:
381 + if cat not in categories:
382 + # Add new category
383 + if raw_body and raw_body[-1] != u'\n':
384 + raw_body += ' '
385 + raw_body += wikiutil.pagelinkmarkup(cat)
386 +
387 + if raw_body and raw_body[-1] != u'\n':
388 + raw_body += u'\n' # Should end with newline!
389 +
390 + return raw_body
391 +
392
30470_multi_templates_and_categories_for_newpage_macro.patch
Example
http://pysvnmanager.ossxp.com/NewPageWithMultiTemplatesSupport
Discussion
Plan
- Priority:
- Assigned to:
- Status: