Attachment 'Include2.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - Include macro
4
5 This macro includes the formatted content of the given page(s). See
6
7 http://purl.net/wiki/moinmaster/HelpOnMacros/Include
8
9 for detailed docs.
10
11 @copyright: 2000-2004 by Jürgen Hermann <jh@web.de>
12 @copyright: 2000-2001 by Richard Jones <richard@bizarsoftware.com.au>
13 @license: GNU GPL, see COPYING for details.
14 """
15
16 #Dependencies = ["pages"] # included page
17 Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks
18
19 import re, StringIO
20 from MoinMoin import wikiutil
21 from MoinMoin.Page import Page
22 from MoinMoin.util import web
23
24 _sysmsg = '<p><strong class="%s">%s</strong></p>'
25
26 ## keep in sync with TableOfContents macro!
27 _arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
28 _arg_level = r',\s*(?P<level>\d*)'
29 _arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
30 _arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
31 _arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
32 _arg_items = r'(,\s*items=(?P<items>\d+))?'
33 _arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
34 _arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
35 _arg_editlink = r'(,\s*(?P<editlink>editlink))?'
36 _arg_tabulate = r'(,\s*(?P<tabulate>tabulate))?'
37 _args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s%s)?$' % (
38 _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
39 _arg_skipitems, _arg_titlesonly, _arg_editlink, _arg_tabulate)
40
41 _title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
42
43 def extract_titles(body, title_re):
44 titles = []
45 for title, _ in title_re.findall(body):
46 h = title.strip()
47 level = 1
48 while h[level:level+1] == '=': level = level+1
49 depth = min(5,level)
50 title_text = h[level:-level].strip()
51 titles.append((title_text, level))
52 return titles
53
54 def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M), called_by_toc=0):
55 request = macro.request
56 _ = request.getText
57
58 # return immediately if getting links for the current page
59 if request.mode_getpagelinks:
60 return ''
61
62 # parse and check arguments
63 args = args_re.match(text)
64 if not args:
65 return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text,))
66
67 # prepare including page
68 result = []
69 print_mode = macro.form.has_key('action') and macro.form['action'][0] == "print"
70 this_page = macro.formatter.page
71 if not hasattr(this_page, '_macroInclude_pagelist'):
72 this_page._macroInclude_pagelist = {}
73
74 # get list of pages to include
75 inc_name = wikiutil.AbsPageName(request, this_page.page_name, args.group('name'))
76 pagelist = [inc_name]
77 if inc_name.startswith("^"):
78 try:
79 inc_match = re.compile(inc_name)
80 except re.error:
81 pass # treat as plain page name
82 else:
83 # Get user filtered readable page list
84 pagelist = request.rootpage.getPageList(filter=inc_match.match)
85
86 # sort and limit page list
87 pagelist.sort()
88 sort_dir = args.group('sort')
89 if sort_dir == 'descending':
90 pagelist.reverse()
91 max_items = args.group('items')
92 if max_items:
93 pagelist = pagelist[:int(max_items)]
94
95 skipitems = 0
96 if args.group("skipitems"):
97 skipitems = int(args.group("skipitems"))
98 titlesonly = args.group('titlesonly')
99 editlink = args.group('editlink')
100 tabulate = args.group('tabulate')
101
102 if tabulate:
103 result.append('<table class="news">')
104
105 # iterate over pages
106 for inc_name in pagelist:
107 if not request.user.may.read(inc_name):
108 continue
109 if this_page._macroInclude_pagelist.has_key(inc_name):
110 result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name,))
111 continue
112 if skipitems:
113 skipitems -= 1
114 continue
115 fmt = macro.formatter.__class__(request, is_included=True)
116 fmt._base_depth = macro.formatter._base_depth
117 inc_page = Page(request, inc_name, formatter=fmt)
118 inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
119
120 # check for "from" and "to" arguments (allowing partial includes)
121 body = inc_page.get_raw_body() + '\n'
122 from_pos = 0
123 to_pos = -1
124 from_re = args.group('from')
125 if from_re:
126 try:
127 from_match = re.compile(from_re, re.M).search(body)
128 except re.error, e:
129 ##result.append("*** fe=%s ***" % e)
130 from_match = re.compile(re.escape(from_re), re.M).search(body)
131 if from_match:
132 from_pos = from_match.end()
133 else:
134 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
135 to_re = args.group('to')
136 if to_re:
137 try:
138 to_match = re.compile(to_re, re.M).search(body, from_pos)
139 except re.error:
140 to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
141 if to_match:
142 to_pos = to_match.start()
143 else:
144 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
145
146 if titlesonly:
147 newbody = []
148 levelstack = []
149 for title, level in extract_titles(body[from_pos:to_pos], title_re):
150 if levelstack:
151 if level > levelstack[-1]:
152 result.append(macro.formatter.bullet_list(1))
153 levelstack.append(level)
154 else:
155 while levelstack and level < levelstack[-1]:
156 result.append(macro.formatter.bullet_list(0))
157 levelstack.pop()
158 if not levelstack or level != levelstack[-1]:
159 result.append(macro.formatter.bullet_list(1))
160 levelstack.append(level)
161 else:
162 result.append(macro.formatter.bullet_list(1))
163 levelstack.append(level)
164 result.append(macro.formatter.listitem(1))
165 result.append(inc_page.link_to(request, title))
166 result.append(macro.formatter.listitem(0))
167 while levelstack:
168 result.append(macro.formatter.bullet_list(0))
169 levelstack.pop()
170 continue
171
172 if from_pos or to_pos != -1:
173 inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
174 ##result.append("*** f=%s t=%s ***" % (from_re, to_re))
175 ##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
176
177 if called_by_toc:
178 result.extend(inc_page.get_raw_body())
179 continue
180
181 if not hasattr(request, "_Include_backto"):
182 request._Include_backto = this_page.page_name
183
184 # do headings
185 level = None
186 if args.group('heading') and args.group('hquote'):
187 heading = args.group('htext') or inc_page.split_title(request)
188 level = 1
189 if args.group('level'):
190 level = int(args.group('level'))
191 if print_mode:
192 result.append(macro.formatter.heading(1, level) +
193 macro.formatter.text(heading) +
194 macro.formatter.heading(0, level))
195 else:
196 import sha
197 from MoinMoin import config
198 # this heading id might produce duplicate ids,
199 # if the same page is included multiple times
200 # Encode stuf we feed into sha module.
201 pntt = (inc_name + heading).encode(config.charset)
202 hid = "head-" + sha.new(pntt).hexdigest()
203 request._page_headings.setdefault(pntt, 0)
204 request._page_headings[pntt] += 1
205 if request._page_headings[pntt] > 1:
206 hid += '-%d'%(request._page_headings[pntt],)
207 result.append(
208 #macro.formatter.heading(1, level, hid,
209 # icons=edit_icon.replace('<img ', '<img align="right" ')) +
210 macro.formatter.heading(1, level, hid) +
211 inc_page.link_to(request, heading, css_class="include-heading-link") +
212 macro.formatter.heading(0, level)
213 )
214
215 # set or increment include marker
216 this_page._macroInclude_pagelist[inc_name] = \
217 this_page._macroInclude_pagelist.get(inc_name, 0) + 1
218
219 # if no heading and not in print mode, then output a helper link
220 if editlink and not (level or print_mode):
221 editlink_html = "\n".join([
222 '<div class="include-link">',
223 inc_page.link_to(request, '[%s]' % (inc_name,), css_class="include-page-link"),
224 inc_page.link_to(request, '[%s]' % (_('edit'),), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}),
225 '</div>',
226 ])
227 else:
228 editlink_html = ""
229 # XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
230
231 if tabulate:
232 body = inc_page.get_raw_body()
233
234 mob = re.compile("#date (.*?)\n").match(body)
235 if mob:
236 date = mob.group(1)
237 body = body[mob.end():]
238 else:
239 date = inc_name
240
241 mob = re.compile("#heading (.*?)\n").match(body)
242 if mob:
243 heading = mob.group(1)
244 body = body[mob.end():]
245 else:
246 heading = "News"
247
248 mob = re.compile("#symbol (.*?)\n").match(body)
249 if mob:
250 symbol = mob.group(1)
251 body = body[mob.end():]
252 else:
253 symbol = "http:/pics/allefant.gif"
254
255 inc_page.set_raw_body(body, modified=True)
256
257 result.append('<tr class="heading"><td>%s</td>' % date)
258 result.append("<td>%s</td><td>%s</td></tr>" % (heading, editlink_html))
259 result.append('<tr><td><img src="%s" alt="news icon" /></td><td colspan="2">' % symbol)
260
261 # output the included page
262 strfile = StringIO.StringIO()
263 request.redirect(strfile)
264 try:
265 cid = request.makeUniqueID("Include_%s" % wikiutil.quoteWikinameFS(inc_page.page_name))
266 inc_page.send_page(request, content_only=1, content_id=cid)
267 result.append(strfile.getvalue())
268 finally:
269 request.redirect()
270
271 # decrement or remove include marker
272 if this_page._macroInclude_pagelist[inc_name] > 1:
273 this_page._macroInclude_pagelist[inc_name] = \
274 this_page._macroInclude_pagelist[inc_name] - 1
275 else:
276 del this_page._macroInclude_pagelist[inc_name]
277
278 if tabulate:
279 result.append("</td></tr>")
280
281 if tabulate:
282 result.append("</table>")
283
284 # return include text
285 return ''.join(result)
286
287 # vim:ts=4:sw=4:et
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.