Attachment 'IncludeModified.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 Juergen Hermann <jh@web.de>,
12 2000-2001 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 generates_headings = True
20
21 import re, StringIO
22 from MoinMoin import wikiutil
23 from MoinMoin.Page import Page
24
25
26 _sysmsg = '<p><strong class="%s">%s</strong></p>'
27
28 ## keep in sync with TableOfContents macro!
29 _arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
30 _arg_level = r',\s*(?P<level>\d*)'
31 _arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
32 _arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
33 _arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
34 _arg_items = r'(,\s*items=(?P<items>\d+))?'
35 _arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
36 _arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
37 _arg_editlink = r'(,\s*(?P<editlink>editlink))?'
38 _args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
39 _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
40 _arg_skipitems, _arg_titlesonly, _arg_editlink)
41
42 _title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
43
44 def extract_titles(body, title_re):
45 titles = []
46 for title, _ in title_re.findall(body):
47 h = title.strip()
48 level = 1
49 while h[level:level+1] == '=':
50 level += 1
51 title_text = h[level:-level].strip()
52 titles.append((title_text, level))
53 return titles
54
55 def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M)):
56 request = macro.request
57 _ = request.getText
58
59 # return immediately if getting links for the current page
60 if request.mode_getpagelinks:
61 return ''
62
63 # parse and check arguments
64 args = text and args_re.match(text)
65 if not args:
66 return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text, ))
67
68 # prepare including page
69 result = []
70 print_mode = request.action in ("print", "format")
71 this_page = macro.formatter.page
72 if not hasattr(this_page, '_macroInclude_pagelist'):
73 this_page._macroInclude_pagelist = {}
74
75 # get list of pages to include
76 inc_name = wikiutil.AbsPageName(this_page.page_name, args.group('name'))
77 pagelist = [inc_name]
78 if inc_name.startswith("^"):
79 try:
80 inc_match = re.compile(inc_name)
81 except re.error:
82 pass # treat as plain page name
83 else:
84 # Get user filtered readable page list
85 pagelist = request.rootpage.getPageList(filter=inc_match.match)
86
87 # sort and limit page list
88 pagelist.sort()
89 sort_dir = args.group('sort')
90 if sort_dir == 'descending':
91 pagelist.reverse()
92 max_items = args.group('items')
93 if max_items:
94 pagelist = pagelist[:int(max_items)]
95
96 skipitems = 0
97 if args.group("skipitems"):
98 skipitems = int(args.group("skipitems"))
99 titlesonly = args.group('titlesonly')
100 editlink = args.group('editlink')
101
102 # iterate over pages
103 for inc_name in pagelist:
104 if not request.user.may.read(inc_name):
105 continue
106 if inc_name in this_page._macroInclude_pagelist:
107 result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name, ))
108 continue
109 if skipitems:
110 skipitems -= 1
111 continue
112 fmt = macro.formatter.__class__(request, is_included=True)
113 fmt._base_depth = macro.formatter._base_depth
114 inc_page = Page(request, inc_name, formatter=fmt)
115 if not inc_page.exists():
116 continue
117 inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
118
119 # check for "from" and "to" arguments (allowing partial includes)
120 body = inc_page.get_raw_body() + '\n'
121 from_pos = 0
122 to_pos = -1
123 from_re = args.group('from')
124 if from_re:
125 try:
126 from_match = re.compile(from_re, re.M).search(body)
127 except re.error:
128 ##result.append("*** fe=%s ***" % e)
129 from_match = re.compile(re.escape(from_re), re.M).search(body)
130 if from_match:
131 from_pos = from_match.end()
132 # else:
133 # result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
134 to_re = args.group('to')
135 if to_re:
136 try:
137 to_match = re.compile(to_re, re.M).search(body, from_pos)
138 except re.error:
139 to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
140 if to_match:
141 to_pos = to_match.start()
142 # else:
143 # result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
144
145 if titlesonly:
146 levelstack = []
147 for title, level in extract_titles(body[from_pos:to_pos], title_re):
148 if levelstack:
149 if level > levelstack[-1]:
150 result.append(macro.formatter.bullet_list(1))
151 levelstack.append(level)
152 else:
153 while levelstack and level < levelstack[-1]:
154 result.append(macro.formatter.bullet_list(0))
155 levelstack.pop()
156 if not levelstack or level != levelstack[-1]:
157 result.append(macro.formatter.bullet_list(1))
158 levelstack.append(level)
159 else:
160 result.append(macro.formatter.bullet_list(1))
161 levelstack.append(level)
162 result.append(macro.formatter.listitem(1))
163 result.append(inc_page.link_to(request, title))
164 result.append(macro.formatter.listitem(0))
165 while levelstack:
166 result.append(macro.formatter.bullet_list(0))
167 levelstack.pop()
168 continue
169
170 if from_pos != 0 or to_pos != -1:
171 inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
172 elif from_re or to_re:
173 inc_page.set_raw_body("", modified=True)
174 else:
175 inc_page.set_raw_body(body[:], modified=True)
176 ##result.append("*** f=%s t=%s ***" % (from_re, to_re))
177 ##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
178
179 if not hasattr(request, "_Include_backto"):
180 request._Include_backto = this_page.page_name
181
182 # do headings
183 level = None
184 if args.group('heading') and args.group('hquote'):
185 heading = args.group('htext') or inc_page.split_title()
186 level = 1
187 if args.group('level'):
188 level = int(args.group('level'))
189 if print_mode:
190 result.append(macro.formatter.heading(1, level) +
191 macro.formatter.text(heading) +
192 macro.formatter.heading(0, level))
193 else:
194 url = inc_page.url(request)
195 result.extend([
196 macro.formatter.heading(1, level, id=heading),
197 macro.formatter.url(1, url, css="include-heading-link"),
198 macro.formatter.text(heading),
199 macro.formatter.url(0),
200 macro.formatter.heading(0, level),
201 ])
202
203 # set or increment include marker
204 this_page._macroInclude_pagelist[inc_name] = \
205 this_page._macroInclude_pagelist.get(inc_name, 0) + 1
206
207 # output the included page
208 strfile = StringIO.StringIO()
209 request.redirect(strfile)
210 try:
211 inc_page.send_page(content_only=True,
212 omit_footnotes=True,
213 count_hit=False)
214 result.append(strfile.getvalue())
215 finally:
216 request.redirect()
217
218 # decrement or remove include marker
219 if this_page._macroInclude_pagelist[inc_name] > 1:
220 this_page._macroInclude_pagelist[inc_name] = \
221 this_page._macroInclude_pagelist[inc_name] - 1
222 else:
223 del this_page._macroInclude_pagelist[inc_name]
224
225 # if no heading and not in print mode, then output a helper link
226 if editlink and not (level or print_mode):
227 if from_pos != 0 or to_pos != -1 or not (from_re or to_re):
228 result.extend([
229 macro.formatter.div(1, css_class="include-link"),
230 inc_page.link_to(request, '[%s]' % (inc_name, ), css_class="include-page-link"),
231 inc_page.link_to(request, '[%s]' % (_('edit'), ), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}),
232 macro.formatter.div(0),
233 ])
234
235 # XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
236
237 # return include text
238 return ''.join(result)
239
240 # 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.