def macro(self): request = self.request groups = [] for groupname in defaultconfig.options: groups.append((groupname, True, defaultconfig.options)) for groupname in defaultconfig.options_no_group_name: groups.append( (groupname, False, defaultconfig.options_no_group_name)) groups.sort() result = moin_page.div() for groupname, addgroup, optsdict in groups: heading, desc, opts = optsdict[groupname] result.append( moin_page.h(attrib={moin_page.outline_level: '1'}, children=[heading])) if desc: result.append(moin_page.p(children=[desc])) table = moin_page.table() result.append(table) header = moin_page.table_header() table.append(header) row = moin_page.table_row() header.append(row) for text in [ _('Variable name'), _('Default'), _('Description'), ]: strong_text = moin_page.strong(children=[text]) row.append(moin_page.table_cell(children=[strong_text])) body = moin_page.table_body() table.append(body) opts = list(opts) opts.sort() for name, default, description in opts: if addgroup: name = groupname + '_' + name if isinstance(default, defaultconfig.DefaultExpression): default_txt = default.text else: default_txt = '%r' % (default, ) if len(default_txt) > 30: default_txt = moin_page.span( attrib={moin_page.title: default_txt}, children=['...']) description = _(description or '') row = moin_page.table_row() body.append(row) row.append(moin_page.table_cell(children=[name])) default = moin_page.code(children=[default_txt]) row.append(moin_page.table_cell(children=[default])) row.append(moin_page.table_cell(children=[description])) return result
def visit_paragraph(self, node): if self.status[-1] == 'footnote': footnote_node = self.footnotes.get(self.footnote_lable, None) if footnote_node: footnote_node.append(node.astext()) node.children = [] else: self.open_moin_page_node(moin_page.p())
def macro_text(self, text): """ Return an ET tree branch representing the markup present in the input text. Used for FootNotes, etc. """ p = moin_page.p() iter_content = _Iter(text) stack = _Stack(p, iter_content=iter_content) self.parse_inline(text, stack, self.inline_re) return p
def block_text_repl(self, _iter_content, stack, text): if stack.top_check('table', 'table-body', 'list', 'block-comment'): stack.clear() if stack.top_check('body', ): element = moin_page.p() stack.push(element) elif stack.top_check('p', ) or len(stack.top()): # we are in a paragraph or multi-line list item, don't loose the whitespace stack.top_append('\n') self.parse_inline(text, stack, self.inline_re)
def block_text_repl(self, _iter_content, stack, text): if stack.top_check('table', 'table-body', 'list'): stack.clear() if stack.top_check('body', 'list-item-body'): element = moin_page.p() stack.push(element) # If we are in a paragraph already, don't loose the whitespace else: stack.top_append('\n') self.parse_inline(text, stack, self.inline_re)
def block_text_repl(self, _iter_content, stack, text): if stack.top_check('table', 'table-body', 'list'): stack.clear() if stack.top_check('body'): element = moin_page.p() stack.push(element) # If we are in a paragraph already, don't loose the whitespace else: stack.top_append('\n') self.parse_inline(text, stack)
def block_text_repl(self, _iter_content, stack, text): if stack.top_check("table", "table-body", "list"): stack.clear() if stack.top_check("body"): element = moin_page.p() stack.push(element) # If we are in a paragraph already, don't loose the whitespace else: stack.top_append("\n") self.parse_inline(text, stack)
def _FootNote_repl(self, args, text, context_block): if not args: # TODO: footnote placing return text = self.macro_text(' '.join(args.positional)) elem_body = moin_page.note_body(children=text) attrib = {moin_page.note_class: 'footnote'} elem = moin_page.note(attrib=attrib, children=[elem_body]) if context_block: return moin_page.p(children=[elem]) return elem
def _FootNote_repl(self, args, text, context_block): if not args: # return a minimal note elem to indicate explicit footnote placement elem = moin_page.note() return elem text = self.macro_text(' '.join(args.positional)) elem_body = moin_page.note_body(children=text) attrib = {moin_page.note_class: 'footnote'} elem = moin_page.note(attrib=attrib, children=[elem_body]) if context_block: return moin_page.p(children=[elem]) return elem
def _FootNote_repl(self, args, text, context_block): if not args: # return a minimal note elem to indicate explicit footnote placement elem = moin_page.note() return elem text = args text = self.macro_text( text) # footnotes may have markup, macro_text is likely overridden elem_body = moin_page.note_body(children=text) attrib = {moin_page.note_class: 'footnote'} elem = moin_page.note(attrib=attrib, children=[elem_body]) if context_block: return moin_page.p(children=[elem]) return elem
def __call__(self, content, arguments, page_url, alternative, context_block): ret = self.macro(content, arguments, page_url, alternative) if context_block: return moin_page.p(children=(ret, )) return ret
def macro(self): if not flaskg.user or not flaskg.user.isSuperUser(): return '' settings = {} for groupname in defaultconfig.options: heading, desc, opts = defaultconfig.options[groupname] for name, default, description in opts: name = groupname + '_' + name if isinstance(default, defaultconfig.DefaultExpression): default = default.value settings[name] = default for groupname in defaultconfig.options_no_group_name: heading, desc, opts = defaultconfig.options_no_group_name[ groupname] for name, default, description in opts: if isinstance(default, defaultconfig.DefaultExpression): default = default.value settings[name] = default result = moin_page.div() result.append( moin_page.h(attrib={moin_page.outline_level: '1'}, children=[_("Wiki configuration")])) desc = _( "This table shows all settings in this wiki that do not have default values. " "Settings that the configuration system doesn't know about are shown in italic, " "those may be due to third-party extensions needing configuration or settings that " "were removed from Moin.") result.append(moin_page.p(children=[desc])) table = moin_page.table() result.append(table) header = moin_page.table_header() table.append(header) row = moin_page.table_row() header.append(row) for text in [ _('Variable name'), _('Setting'), ]: strong_text = moin_page.strong(children=[text]) row.append(moin_page.table_cell(children=[strong_text])) body = moin_page.table_body() table.append(body) def iter_vnames(cfg): dedup = {} for name in cfg.__dict__: dedup[name] = True yield name, cfg.__dict__[name] for cls in cfg.__class__.mro(): if cls == defaultconfig.ConfigFunctionality: break for name in cls.__dict__: if not name in dedup: dedup[name] = True yield name, cls.__dict__[name] found = [] for vname, value in iter_vnames(app.cfg): if hasattr(defaultconfig.ConfigFunctionality, vname): continue if vname in settings and settings[vname] == value: continue found.append((vname, value)) found.sort() for vname, value in found: if not vname in settings: vname = moin_page.emphasis(children=[vname]) vtxt = '%r' % (value, ) row = moin_page.table_row() body.append(row) row.append(moin_page.table_cell(children=[vname])) vtxt_code = moin_page.code(children=[vtxt]) row.append(moin_page.table_cell(children=[vtxt_code])) return result
def invalid_args(self, elem, all_nowiki_args): """Insert an error message into output.""" message = _('Defaulting to plain text due to invalid arguments: "{arguments}"').format(arguments=all_nowiki_args[0]) admonition = moin_page.div(attrib={moin_page.class_: 'error'}, children=[moin_page.p(children=[message])]) elem.append(admonition)
def error_message(msg): txt = moin_page.p(children=(text, )) msg = moin_page.p(children=(msg, )) msg.set(moin_page.class_, 'moin-error') div = moin_page.div(children=(txt, msg)) return div
def recurse(self, elem, page_href): # on first call, elem.tag.name=='page'. # Descendants (body, div, p, include, page, etc.) are processed by recursing through DOM # stack is used to detect transclusion loops page_href_new = elem.get(self.tag_page_href) if page_href_new: page_href_new = Iri(page_href_new) if page_href_new != page_href: page_href = page_href_new self.stack.append(page_href) else: self.stack.append(None) else: self.stack.append(None) try: if elem.tag == self.tag_xi_include: # we have already recursed several levels and found a transclusion: "{{SomePage}}" or similar # process the transclusion and add it to the DOM. Subsequent recursions will traverse through # the transclusion's elements. href = elem.get(self.tag_xi_href) xpointer = elem.get(self.tag_xi_xpointer) xp_include_pages = None xp_include_sort = None xp_include_items = None xp_include_skipitems = None xp_include_heading = None xp_include_level = None if xpointer: xp = XPointer(xpointer) xp_include = None xp_namespaces = {} for entry in xp: uri = None name = entry.name.split(':', 1) if len(name) > 1: prefix, name = name uri = xp_namespaces.get(prefix, False) else: name = name[0] if uri is None and name == 'xmlns': d_prefix, d_uri = entry.data.split('=', 1) xp_namespaces[d_prefix] = d_uri elif uri == moin_page.namespace and name == 'include': xp_include = XPointer(entry.data) if xp_include: for entry in xp_include: name, data = entry.name, entry.data_unescape if name == 'pages': xp_include_pages = data elif name == 'sort': xp_include_sort = data elif name == 'items': xp_include_items = int(data) elif name == 'skipitems': xp_include_skipitems = int(data) elif name == 'heading': xp_include_heading = data elif name == 'level': xp_include_level = data if href: # We have a single page to transclude href = Iri(href) link = Iri(scheme='wiki', authority='') if href.scheme == 'wiki': if href.authority: raise ValueError( "can't handle xinclude for non-local authority" ) else: path = href.path[1:] elif href.scheme == 'wiki.local': page = page_href path = href.path if path[0] == '': # /subitem tmp = page.path[1:] tmp.extend(path[1:]) path = tmp elif path[0] == '..': # ../sisteritem path = page.path[1:] + path[1:] else: raise ValueError( "can't handle xinclude for schemes other than wiki or wiki.local" ) link.path = path if flaskg.user.may.read(unicode(path)): page = Item.create(unicode(path)) pages = ((page, link), ) else: # ACLs prevent user from viewing a transclusion - show message message = moin_page.p(children=(_( 'Access Denied, transcluded content suppressed.'))) attrib = {html.class_: 'warning'} div = ET.Element(moin_page.div, attrib, children=(message, )) container = ET.Element(moin_page.body, children=(div, )) return [ container, 0 ] # replace transclusion with container's child elif xp_include_pages: # XXX we currently interpret xp_include_pages as wildcard, but it should be regex # for compatibility with moin 1.9. whoosh has upcoming regex support, but it is not # released yet. if xp_include_pages.startswith('^'): # get rid of the leading ^ the Include macro needed to get into "regex mode" xp_include_pages = xp_include_pages[1:] query = And([ Term(WIKINAME, app.cfg.interwikiname), Wildcard(NAME_EXACT, xp_include_pages) ]) reverse = xp_include_sort == 'descending' results = flaskg.storage.search(query, sortedby=NAME_EXACT, reverse=reverse, limit=None) pagelist = [result[NAME] for result in results] if xp_include_skipitems is not None: pagelist = pagelist[xp_include_skipitems:] if xp_include_items is not None: pagelist = pagelist[xp_include_items + 1:] pages = ((Item.create(p), Iri(scheme='wiki', authority='', path='/' + p)) for p in pagelist) included_elements = [] for page, p_href in pages: if p_href.path[0] != '/': p_href.path = IriPath('/' + '/'.join(p_href.path)) if p_href in self.stack: # we have a transclusion loop, create an error message showing list of pages forming loop loop = self.stack[self.stack.index(p_href):] loop = [ u'{0}'.format(ref.path[1:]) for ref in loop if ref is not None ] + [page.name] msg = u'Error: Transclusion loop via: ' + u', '.join( loop) attrib = {html.class_: 'moin-error'} strong = ET.Element(moin_page.strong, attrib, (msg, )) included_elements.append(strong) continue # TODO: Is this correct? if not flaskg.user.may.read(page.name): continue if xp_include_heading is not None: attrib = {self.tag_href: p_href} children = (xp_include_heading or page.name, ) elem_a = ET.Element(self.tag_a, attrib, children=children) attrib = { self.tag_outline_level: xp_include_level or '1' } elem_h = ET.Element(self.tag_h, attrib, children=(elem_a, )) included_elements.append(elem_h) page_doc = page.content.internal_representation( attributes=Arguments(keyword=elem.attrib)) self.recurse(page_doc, page_href) # The href needs to be an absolute URI, without the prefix "wiki://" page_doc = mark_item_as_transclusion(page_doc, p_href.path) included_elements.append(page_doc) if len(included_elements) > 1: # use a div as container result = ET.Element(self.tag_div) result.extend(included_elements) elif included_elements: result = included_elements[0] else: result = None # end of processing for transclusion; the "result" will get inserted into the DOM below return result # Traverse the DOM by calling self.recurse with each child of the current elem. # Starting elem.tag.name=='page'. container = [] i = 0 while i < len(elem): child = elem[i] if isinstance(child, ET.Node): ret = self.recurse(child, page_href) if ret: # Either child or a descendant of child is a transclusion. # See top of this script for notes on why these DOM adjustments are required. if isinstance(ret, ET.Node ) and elem.tag.name in NO_BLOCK_CHILDREN: body = ret[0] if len(body) == 0: # the transcluded item is empty, insert an empty span into DOM attrib = Attributes(ret).convert() elem[i] = ET.Element(moin_page.span, attrib=attrib) elif (isinstance(body[0], ET.Node) and (len(body) > 1 or body[0].tag.name not in ('p', 'object', 'a'))): # Complex case: "some text {{BlockItem}} more text" or "\n{{BlockItem}}\n" where # the BlockItem body contains multiple p's, a table, preformatted text, etc. # These block elements cannot be made a child of the current elem, so we create # a container to replace elem. # Create nodes to hold any siblings before and after current child (elem[i]) before = copy.deepcopy(elem) after = copy.deepcopy(elem) before[:] = elem[0:i] after[:] = elem[i + 1:] if len(before): # there are siblings before transclude, save them in container container.append(before) new_trans_ptr = len(container) # get attributes from page node; # we expect {class: "moin-transclusion"; data-href: "http://some.org/somepage"} attrib = Attributes(ret).convert() # current elem will likely be replaced by container so we need to copy data-lineno attr if html.data_lineno in elem.attrib: attrib[html.data_lineno] = elem.attrib[ html.data_lineno] # make new div node to hold transclusion, copy children, and save in container div = ET.Element(moin_page.div, attrib=attrib, children=body[:]) container.append( div) # new_trans_ptr is index to this if len(after): container.append(after) if elem.tag.name == 'a': # invalid input [[MyPage|{{BlockItem}}]], # best option is to retain A-tag and fail html validation # TODO: error may not be obvious to user - add error message elem[i] = div else: # move up 1 level in recursion where elem becomes the child and # is usually replaced by container return [container, new_trans_ptr] else: # default action for inline transclusions or odd things like circular transclusion error messages classes = child.attrib.get(html.class_, '').split() classes += ret.attrib.get(html.class_, '').split() ret.attrib[html.class_] = ' '.join(classes) elem[i] = ret elif isinstance(ret, types.ListType): # a container has been returned. # Note: there are multiple places where a container may be constructed ret_container, trans_ptr = ret # trans_ptr points to the transclusion within ret_container. # Here the transclusion will always contain a block level element if elem.tag.name in NO_BLOCK_CHILDREN: # Complex case, transclusion effects grand-parent, great-grand-parent, e.g.: # "/* comment {{BlockItem}} */" or "text ''italic {{BlockItem}} italic'' text" # elem is an inline element, build a bigger container to replace elem's parent, before = copy.deepcopy(elem) after = copy.deepcopy(elem) before[:] = elem[0:i] + ret_container[ 0:trans_ptr] after[:] = ret_container[trans_ptr + 1:] + elem[i + 1:] if len(before): container.append(before) new_trans_ptr = len(container) # child may have classes like "comment" that must be added to transcluded element classes = child.attrib.get( moin_page.class_, '').split() # must use moin_page.class_ above, but use html.class below per html_out.py code classes += ret_container[trans_ptr].attrib.get( html.class_, '').split() ret_container[trans_ptr].attrib[ html.class_] = ' '.join(classes) container.append(ret_container[trans_ptr] ) # the transclusion if len(after): container.append(after) return [container, new_trans_ptr] else: # elem is a block element for grandchild in child: if isinstance( grandchild, ET.Node ) and grandchild.tag.name == u'include': # the include may have classes that must be added to transcluded element classes = grandchild.attrib.get( html.class_, '').split() classes += ret_container[ trans_ptr].attrib.get( html.class_, '').split() ret_container[trans_ptr].attrib[ html.class_] = ' '.join(classes) # replace child element with the container generated in lower recursion elem[i:i + 1] = ret_container # elem[i] is the child else: # default action for any ret not fitting special cases above, # e.g. tranclusion is within a table cell elem[i] = ret # we are finished with this child, advance to next sibling i += 1 finally: self.stack.pop()
def recurse(self, elem, page_href): # on first call, elem.tag.name=='page'. # Descendants (body, div, p, include, page, etc.) are processed by recursing through DOM # stack is used to detect transclusion loops page_href_new = elem.get(self.tag_page_href) if page_href_new: page_href_new = Iri(page_href_new) if page_href_new != page_href: page_href = page_href_new self.stack.append(page_href) else: self.stack.append(None) else: self.stack.append(None) try: if elem.tag == self.tag_xi_include: # we have already recursed several levels and found a transclusion: "{{SomePage}}" or similar # process the transclusion and add it to the DOM. Subsequent recursions will traverse through # the transclusion's elements. href = elem.get(self.tag_xi_href) xpointer = elem.get(self.tag_xi_xpointer) xp_include_pages = None xp_include_sort = None xp_include_items = None xp_include_skipitems = None xp_include_heading = None xp_include_level = None if xpointer: xp = XPointer(xpointer) xp_include = None xp_namespaces = {} for entry in xp: uri = None name = entry.name.split(':', 1) if len(name) > 1: prefix, name = name uri = xp_namespaces.get(prefix, False) else: name = name[0] if uri is None and name == 'xmlns': d_prefix, d_uri = entry.data.split('=', 1) xp_namespaces[d_prefix] = d_uri elif uri == moin_page.namespace and name == 'include': xp_include = XPointer(entry.data) if xp_include: for entry in xp_include: name, data = entry.name, entry.data_unescape if name == 'pages': xp_include_pages = data elif name == 'sort': xp_include_sort = data elif name == 'items': xp_include_items = int(data) elif name == 'skipitems': xp_include_skipitems = int(data) elif name == 'heading': xp_include_heading = data elif name == 'level': xp_include_level = data if href: # We have a single page to transclude href = Iri(href) link = Iri(scheme='wiki', authority='') if href.scheme == 'wiki': if href.authority: raise ValueError("can't handle xinclude for non-local authority") else: path = href.path[1:] elif href.scheme == 'wiki.local': page = page_href path = href.path if path[0] == '': # /subitem tmp = page.path[1:] tmp.extend(path[1:]) path = tmp elif path[0] == '..': # ../sisteritem path = page.path[1:] + path[1:] else: raise ValueError("can't handle xinclude for schemes other than wiki or wiki.local") link.path = path if flaskg.user.may.read(unicode(path)): page = Item.create(unicode(path)) pages = ((page, link), ) else: # ACLs prevent user from viewing a transclusion - show message message = moin_page.p(children=(_('Access Denied, transcluded content suppressed.'))) attrib = {html.class_: 'warning'} div = ET.Element(moin_page.div, attrib, children=(message, )) container = ET.Element(moin_page.body, children=(div, )) return [container, 0] # replace transclusion with container's child elif xp_include_pages: # XXX we currently interpret xp_include_pages as wildcard, but it should be regex # for compatibility with moin 1.9. whoosh has upcoming regex support, but it is not # released yet. if xp_include_pages.startswith('^'): # get rid of the leading ^ the Include macro needed to get into "regex mode" xp_include_pages = xp_include_pages[1:] query = And([Term(WIKINAME, app.cfg.interwikiname), Wildcard(NAME_EXACT, xp_include_pages)]) reverse = xp_include_sort == 'descending' results = flaskg.storage.search(query, sortedby=NAME_EXACT, reverse=reverse, limit=None) pagelist = [result[NAME] for result in results] if xp_include_skipitems is not None: pagelist = pagelist[xp_include_skipitems:] if xp_include_items is not None: pagelist = pagelist[xp_include_items + 1:] pages = ((Item.create(p), Iri(scheme='wiki', authority='', path='/' + p)) for p in pagelist) included_elements = [] for page, p_href in pages: if p_href.path[0] != '/': p_href.path = IriPath('/' + '/'.join(p_href.path)) if p_href in self.stack: # we have a transclusion loop, create an error message showing list of pages forming loop loop = self.stack[self.stack.index(p_href):] loop = [u'{0}'.format(ref.path[1:]) for ref in loop if ref is not None] + [page.name] msg = u'Error: Transclusion loop via: ' + u', '.join(loop) attrib = {html.class_: 'moin-error'} strong = ET.Element(moin_page.strong, attrib, (msg, )) included_elements.append(strong) continue # TODO: Is this correct? if not flaskg.user.may.read(page.name): continue if xp_include_heading is not None: attrib = {self.tag_href: p_href} children = (xp_include_heading or page.name, ) elem_a = ET.Element(self.tag_a, attrib, children=children) attrib = {self.tag_outline_level: xp_include_level or '1'} elem_h = ET.Element(self.tag_h, attrib, children=(elem_a, )) included_elements.append(elem_h) page_doc = page.content.internal_representation(attributes=Arguments(keyword=elem.attrib)) self.recurse(page_doc, page_href) # The href needs to be an absolute URI, without the prefix "wiki://" page_doc = mark_item_as_transclusion(page_doc, p_href.path) included_elements.append(page_doc) if len(included_elements) > 1: # use a div as container result = ET.Element(self.tag_div) result.extend(included_elements) elif included_elements: result = included_elements[0] else: result = None # end of processing for transclusion; the "result" will get inserted into the DOM below return result # Traverse the DOM by calling self.recurse with each child of the current elem. # Starting elem.tag.name=='page'. container = [] i = 0 while i < len(elem): child = elem[i] if isinstance(child, ET.Node): ret = self.recurse(child, page_href) if ret: # Either child or a descendant of child is a transclusion. # See top of this script for notes on why these DOM adjustments are required. if isinstance(ret, ET.Node) and elem.tag.name in NO_BLOCK_CHILDREN: body = ret[0] if len(body) == 0: # the transcluded item is empty, insert an empty span into DOM attrib = Attributes(ret).convert() elem[i] = ET.Element(moin_page.span, attrib=attrib) elif (isinstance(body[0], ET.Node) and (len(body) > 1 or body[0].tag.name not in ('p', 'object', 'a'))): # Complex case: "some text {{BlockItem}} more text" or "\n{{BlockItem}}\n" where # the BlockItem body contains multiple p's, a table, preformatted text, etc. # These block elements cannot be made a child of the current elem, so we create # a container to replace elem. # Create nodes to hold any siblings before and after current child (elem[i]) before = copy.deepcopy(elem) after = copy.deepcopy(elem) before[:] = elem[0:i] after[:] = elem[i + 1:] if len(before): # there are siblings before transclude, save them in container container.append(before) new_trans_ptr = len(container) # get attributes from page node; # we expect {class: "moin-transclusion"; data-href: "http://some.org/somepage"} attrib = Attributes(ret).convert() # current elem will likely be replaced by container so we need to copy data-lineno attr if html.data_lineno in elem.attrib: attrib[html.data_lineno] = elem.attrib[html.data_lineno] # make new div node to hold transclusion, copy children, and save in container div = ET.Element(moin_page.div, attrib=attrib, children=body[:]) container.append(div) # new_trans_ptr is index to this if len(after): container.append(after) if elem.tag.name == 'a': # invalid input [[MyPage|{{BlockItem}}]], # best option is to retain A-tag and fail html validation # TODO: error may not be obvious to user - add error message elem[i] = div else: # move up 1 level in recursion where elem becomes the child and # is usually replaced by container return [container, new_trans_ptr] else: # default action for inline transclusions or odd things like circular transclusion error messages classes = child.attrib.get(html.class_, '').split() classes += ret.attrib.get(html.class_, '').split() ret.attrib[html.class_] = ' '.join(classes) elem[i] = ret elif isinstance(ret, types.ListType): # a container has been returned. # Note: there are multiple places where a container may be constructed ret_container, trans_ptr = ret # trans_ptr points to the transclusion within ret_container. # Here the transclusion will always contain a block level element if elem.tag.name in NO_BLOCK_CHILDREN: # Complex case, transclusion effects grand-parent, great-grand-parent, e.g.: # "/* comment {{BlockItem}} */" or "text ''italic {{BlockItem}} italic'' text" # elem is an inline element, build a bigger container to replace elem's parent, before = copy.deepcopy(elem) after = copy.deepcopy(elem) before[:] = elem[0:i] + ret_container[0:trans_ptr] after[:] = ret_container[trans_ptr + 1:] + elem[i + 1:] if len(before): container.append(before) new_trans_ptr = len(container) # child may have classes like "comment" that must be added to transcluded element classes = child.attrib.get(moin_page.class_, '').split() # must use moin_page.class_ above, but use html.class below per html_out.py code classes += ret_container[trans_ptr].attrib.get(html.class_, '').split() ret_container[trans_ptr].attrib[html.class_] = ' '.join(classes) container.append(ret_container[trans_ptr]) # the transclusion if len(after): container.append(after) return [container, new_trans_ptr] else: # elem is a block element for grandchild in child: if isinstance(grandchild, ET.Node) and grandchild.tag.name == u'include': # the include may have classes that must be added to transcluded element classes = grandchild.attrib.get(html.class_, '').split() classes += ret_container[trans_ptr].attrib.get(html.class_, '').split() ret_container[trans_ptr].attrib[html.class_] = ' '.join(classes) # replace child element with the container generated in lower recursion elem[i:i + 1] = ret_container # elem[i] is the child else: # default action for any ret not fitting special cases above, # e.g. tranclusion is within a table cell elem[i] = ret # we are finished with this child, advance to next sibling i += 1 finally: self.stack.pop()
def visit_attribution(self, node): attrib = {html.class_: 'moin-rst-attribution'} self.open_moin_page_node(moin_page.p(attrib=attrib))