Пример #1
0
    def traverse_tree(self, elem, page=None, __tag_page_href=moin_page.page_href,
                      __tag_link=_tag_xlink_href, __tag_include=_tag_xinclude_href):
        """
        Traverses the tree and handles each element appropriately
        """
        new_page_href = elem.get(__tag_page_href)
        if new_page_href:
            page = Iri(new_page_href)

        xlink_href = elem.get(__tag_link)
        xinclude_href = elem.get(__tag_include)
        if xlink_href:
            xlink_href = Iri(xlink_href)
            if xlink_href.scheme == 'wiki.local':
                self.handle_wikilocal_links(elem, xlink_href, page)
            elif xlink_href.scheme == 'wiki':
                self.handle_wiki_links(elem, xlink_href)
            elif xlink_href.scheme:
                self.handle_external_links(elem, xlink_href)

        elif xinclude_href:
            xinclude_href = Iri(xinclude_href)
            if xinclude_href.scheme == 'wiki.local':
                self.handle_wikilocal_transclusions(elem, xinclude_href, page)
            elif xinclude_href.scheme == 'wiki':
                self.handle_wiki_transclusions(elem, xinclude_href)

        elif xlink_href == u'':
            # ReST link to page fragment
            elem.set(self._tag_xlink_href, u'#' + elem.text.replace(' ', '_'))

        for child in elem.iter_elements():
            self.traverse_tree(child, page)

        return elem
Пример #2
0
    def inline_object_repl(self, stack, object, object_url=None, object_item=None,
                           object_text=None, object_args=None):
        """Handles objects transcluded within the page."""
        if object_args:
            args = parse_arguments(object_args).keyword  # XXX needs different parsing
        else:
            args = {}

        query_keys = {}
        attrib = {}
        whitelist = ['width', 'height', 'class']
        for attr, value in args.iteritems():
            if attr.startswith('&'):
                query_keys[attr[1:]] = value
            elif attr in whitelist:
                attrib[html(attr)] = value
        if object_text:
            attrib[html.alt] = object_text
        if object_item is not None:
            # img tag
            query = url_encode(query_keys, charset=CHARSET, encode_keys=True)
            # TODO: moin 1.9 needed this for an attached file; move functionality to script/migration/moin/import19.py
            att = 'attachment:'
            if object_item.startswith(att):
                object_item = '/' + object_item[len(att):]  # now we have a subitem
            target = Iri(scheme='wiki.local', path=object_item, query=query, fragment=None)
            attrib[xinclude.href] = target
            element = xinclude.include(attrib=attrib)
            stack.top_append(element)
        else:
            # object tag
            target = Iri(object_url)
            attrib[xlink.href] = target
            element = moin_page.object(attrib)
            stack.top_append(element)
Пример #3
0
    def visit_reference(self, node):
        refuri = node.get('refuri', u'')
        if refuri.startswith(u'<<') and refuri.endswith(u'>>'):  # moin macro
            macro_name = refuri[2:-2].split(u'(')[0]
            if macro_name == u"TableOfContents":
                arguments = refuri[2:-2].split(u'(')[1][:-1].split(u',')
                node = moin_page.table_of_content()
                self.open_moin_page_node(node)
                if arguments and arguments[0]:
                    node.set(moin_page.outline_level, arguments[0])
                return
            if macro_name == u"Include":
                # include macros are expanded by include.py similar to transclusions
                # rst include handles only wiki pages and does not support additional arguments like moinwiki
                arguments = refuri[2:-2].split(u'(')[1][:-1].split(u',')
                link = Iri(scheme=u'wiki.local', path=arguments)
                node = xinclude.include(
                    attrib={
                        xinclude.href: link,
                        moin_page.alt: refuri,
                        moin_page.content_type: 'x-moin/macro;name=' +
                        macro_name,
                    })
                self.open_moin_page_node(node)
                return
            try:
                arguments = refuri[2:-2].split(u'(')[1][:-1]
            except IndexError:
                arguments = u''  # <<DateTime>>

            self.open_moin_page_node(
                moin_page.inline_part(
                    attrib={
                        moin_page.content_type:
                        "x-moin/macro;name={0}".format(macro_name)
                    }))
            if arguments:
                self.open_moin_page_node(moin_page.arguments())
                self.open_moin_page_node(arguments)
                self.close_moin_page_node()
                self.close_moin_page_node()
            return

        if not allowed_uri_scheme(refuri):
            self.visit_error(node)
            return
        if refuri == u'':
            # build a link to a heading or an explicitly defined anchor
            refuri = Iri(scheme='wiki.local',
                         fragment=node.attributes['name'].replace(' ', '_'))
        self.open_moin_page_node(moin_page.a(attrib={xlink.href: refuri}))
Пример #4
0
    def visit_image(self, node):
        """
        Processes images and other transcluded objects.
        """
        whitelist = [
            'width',
            'height',
            'alt',
        ]
        attrib = {}
        for key in whitelist:
            if node.get(key):
                attrib[html(key)] = node.get(key)

        # there is no 'scale' attribute, hence absent from whitelist, handled separately
        if node.get('scale'):
            scaling_factor = int(node.get('scale')) / 100.0
            for key in ('width', 'height'):
                if html(key) in attrib:
                    attrib[html(key)] = int(
                        int(attrib[html(key)]) * scaling_factor)

        # "align" parameter is invalid in HTML5. Convert it to a class defined in userstyles.css.
        userstyles = {
            'left': 'left',
            'center': 'center',
            'right': 'right',
            'top':
            'top',  # rst parser creates error messages for top, bottom, and middle
            'bottom': 'bottom',
            'middle': 'middle',
        }
        alignment = userstyles.get(node.get('align'))
        if alignment:
            attrib[html.class_] = alignment

        url = Iri(node['uri'])
        if url.scheme is None:
            # img
            target = Iri(scheme='wiki.local', path=node['uri'], fragment=None)
            attrib[xinclude.href] = target
            new_node = xinclude.include(attrib=attrib)
        else:
            # obj
            new_node = moin_page.object(attrib)
            new_node.set(xlink.href, url)

        self.open_moin_page_node(new_node)
Пример #5
0
def test_Iri_quote_1():
    u = Iri(scheme=u'wiki', authority=u'authority_ä%?#',
            path=u'/path_ä%?#', query=u'query_ä%?#', fragment=u'fragment_ä%?#')
    assert u.scheme == u'wiki'
    assert u.authority == u'authority_ä%?#'
    authority = u'authority_ä%25%3F%23'
    assert u.authority.fullquoted == authority
    assert u.authority.quoted == u'authority_ä%25?#'
    assert u.authority.urlquoted == u'authority_%C3%A4%25%3F%23'
    assert u.path == u'/path_ä%?#'
    path = u'/path_ä%25%3F%23'
    assert u.path.fullquoted == path
    assert u.path.quoted == u'/path_ä%25?#'
    assert u.path.urlquoted == u'/path_%C3%A4%25%3F%23'
    assert u.query == u'query_ä%?#'
    query = u'query_ä%25?%23'
    assert u.query.fullquoted == query
    assert u.query.quoted == u'query_ä%25?#'
    assert u.query.urlquoted == u'query_%C3%A4%25?%23'
    assert u.fragment == u'fragment_ä%?#'
    fragment = u'fragment_ä%25?%23'
    assert u.fragment.fullquoted == fragment
    assert u.fragment.quoted == u'fragment_ä%25?#'
    assert u.fragment.urlquoted == u'fragment_%C3%A4%25?%23'
    assert unicode(u) == u'wiki://{0}{1}?{2}#{3}'.format(authority, path, query, fragment)
Пример #6
0
def test_Iri_init_1():
    u = Iri(scheme='wiki', path='/StartSeite', query='action=raw')
    assert u.scheme == 'wiki'
    assert u.authority is None
    assert u.path == '/StartSeite'
    assert u.query == 'action=raw'
    assert u.fragment is None
Пример #7
0
    def __call__(self, rev, contenttype=None, arguments=None):
        item_name = rev.item.name
        query_keys = {'do': 'get', 'rev': rev.revid}
        attrib = {}
        if arguments:
            query = arguments.keyword.get(xinclude.href)
            if query and query.query:
                # query.query value is similar to  "w=75" given a transclusion "{{jpeg||&w=75 class="top"}}"
                query_keys.update(url_decode(query.query))
            attrib = arguments.keyword

        query = url_encode(query_keys, charset=CHARSET, encode_keys=True)

        attrib.update({
            moin_page.type_:
            unicode(self.input_type),
            xlink.href:
            Iri(scheme='wiki', authority='', path='/' + item_name,
                query=query),
        })

        obj = moin_page.object_(attrib=attrib, children=[
            item_name,
        ])
        body = moin_page.body(children=(obj, ))
        return moin_page.page(children=(body, ))
Пример #8
0
 def inline_link_repl(self,
                      stack,
                      link,
                      link_url=None,
                      link_item=None,
                      link_text=None,
                      link_interwiki_site=None,
                      link_interwiki_item=None):
     """Handle all kinds of links."""
     if link_interwiki_site:
         if is_known_wiki(link_interwiki_site):
             link = Iri(scheme='wiki',
                        authority=link_interwiki_site,
                        path='/' + link_interwiki_item)
             element = moin_page.a(attrib={xlink.href: link})
             stack.push(element)
             if link_text:
                 self.parse_inline(link_text, stack, self.inlinedesc_re)
             else:
                 stack.top_append(link_interwiki_item)
             stack.pop()
             return
         else:
             # assume local language uses ":" inside of words, set link_item and continue
             link_item = '{0}:{1}'.format(link_interwiki_site,
                                          link_interwiki_item)
     if link_item is not None:
         att = 'attachment:'  # moin 1.9 needed this for an attached file
         if link_item.startswith(att):
             link_item = '/' + link_item[len(att):]  # now we have a subitem
         # we have Anchor macro, so we support anchor links despite lack of docs in Creole spec
         if '#' in link_item:
             path, fragment = link_item.rsplit('#', 1)
         else:
             path, fragment = link_item, None
         target = Iri(scheme='wiki.local', path=path, fragment=fragment)
         text = link_item
     else:
         target = Iri(link_url)
         text = link_url
     element = moin_page.a(attrib={xlink.href: target})
     stack.push(element)
     if link_text:
         self.parse_inline(link_text, stack, self.inlinedesc_re)
     else:
         stack.top_append(text)
     stack.pop()
Пример #9
0
def test_Iri_init_2():
    i = 'wiki://MoinMoin/StartSeite?action=raw#body'
    u = Iri(i, scheme='newwiki', path='/newStartSeite', query='action=false')
    assert u.scheme == 'newwiki'
    assert u.authority == 'MoinMoin'
    assert u.path == '/newStartSeite'
    assert u.query == 'action=false'
    assert u.fragment == 'body'
Пример #10
0
 def __call__(self, rev, contenttype=None, arguments=None):
     item_name = rev.item.fqname.value
     attrib = {
         xlink.href: Iri(scheme='wiki', authority='', path='/' + item_name, query='do=modify'),
     }
     a = moin_page.a(attrib=attrib, children=[_("%(item_name)s does not exist. Create it?", item_name=item_name)])
     body = moin_page.body(children=(a, ))
     return moin_page.page(children=(body, ))
Пример #11
0
def test_Iri_quote_2():
    authority = u'authority_ä%25%3F%23'
    path = u'/path_ä%25%3F%23'
    query = u'query_ä%25?%23'
    fragment = u'fragment_ä%25?%23'
    i = u'wiki://{0}{1}?{2}#{3}'.format(authority, path, query, fragment)
    u = Iri(i)
    assert unicode(u) == i
Пример #12
0
 def __call__(self, rev, contenttype=None, arguments=None):
     item_name = rev.item.name or rev.meta['name'][0]
     attrib = {
         xlink.href: Iri(scheme='wiki', authority='', path='/' + item_name,
                         query='do=get&rev={0}'.format(rev.revid)),
     }
     a = moin_page.a(attrib=attrib, children=[u"Download {0}.".format(item_name)])
     body = moin_page.body(children=(a, ))
     return moin_page.page(children=(body, ))
Пример #13
0
def test_Iri_2():
    i = 'wiki://MoinMoin/StartSeite?action=raw#body'
    u = Iri(i)
    assert u.scheme == 'wiki'
    assert u.authority == 'MoinMoin'
    assert u.path == '/StartSeite'
    assert u.query == 'action=raw'
    assert u.fragment == 'body'
    assert unicode(u) == i

    i = 'wiki:///StartSeite?action=raw#body'
    u = Iri(i)
    assert u.scheme == 'wiki'
    assert u.authority == ''
    assert u.path == '/StartSeite'
    assert u.query == 'action=raw'
    assert u.fragment == 'body'
    assert unicode(u) == i
Пример #14
0
def test_Iri_3():
    i = 'wiki.local:StartSeite?action=raw#body'
    u = Iri(i)
    assert u.scheme == 'wiki.local'
    assert u.authority is None
    assert u.path == 'StartSeite'
    assert u.query == 'action=raw'
    assert u.fragment == 'body'
    assert unicode(u) == i
Пример #15
0
 def visit_img(self, element):
     """
     <img src="URI" /> --> <object xlink:href="URI />
     """
     attrib = {}
     url = Iri(element.attrib.get('src'))
     if element.attrib.get('alt'):
         attrib[html.alt] = element.attrib.get('alt')
     if element.attrib.get('title'):
         attrib[html.title_] = element.attrib.get('title')
     if url.scheme is None:
         # img tag
         target = Iri(scheme='wiki.local', path=element.attrib.get("src"), fragment=None)
         attrib[xinclude.href] = target
         new_node = xinclude.include(attrib=attrib)
     else:
         # object tag
         attrib[xlink.href] = url
         new_node = moin_page.object(attrib)
     return new_node
Пример #16
0
    def inline_freelink_repl(self,
                             stack,
                             freelink,
                             freelink_bang=None,
                             freelink_interwiki_page=None,
                             freelink_interwiki_ref=None,
                             freelink_page=None,
                             freelink_email=None):
        if freelink_bang:
            stack.top_append(freelink)
            return

        attrib = {}

        if freelink_page:
            page = freelink_page.encode('utf-8')
            if '#' in page:
                path, fragment = page.rsplit('#', 1)
            else:
                path, fragment = page, None
            link = Iri(scheme='wiki.local', path=path, fragment=fragment)
            text = freelink_page

        elif freelink_email:
            link = 'mailto:' + freelink_email
            text = freelink_email

        else:
            if not is_known_wiki(freelink_interwiki_ref):
                stack.top_append(freelink)
                return

            link = Iri(scheme='wiki',
                       authority=freelink_interwiki_ref,
                       path='/' + freelink_interwiki_page)
            text = freelink_interwiki_page

        attrib[xlink.href] = link

        element = moin_page.a(attrib, children=[text])
        stack.top_append(element)
Пример #17
0
 def process_name(self, member_name):
     name = unicode(member_name, 'utf-8')
     attrib = {
         xlink.href:
         Iri(scheme='wiki',
             authority='',
             path='/' + self.item_name,
             query=u'do=get&member={0}'.format(name)),
     }
     return moin_page.a(attrib=attrib, children=[
         name,
     ])
Пример #18
0
 def handle_wiki_links(self, elem, input):
     wiki_name = 'Self'
     if input.authority and input.authority.host:
         wn = unicode(input.authority.host)
         if is_known_wiki(wn):
             # interwiki link
             elem.set(moin_page.class_, 'moin-interwiki')
             wiki_name = wn
     item_name = unicode(input.path[1:])
     endpoint, rev, query = self._get_do_rev(input.query)
     url = url_for_item(item_name, wiki_name=wiki_name, rev=rev, endpoint=endpoint)
     link = Iri(url, query=query, fragment=input.fragment)
     elem.set(self._tag_xlink_href, link)
Пример #19
0
 def inline_object_repl(self, stack, object, object_page=None, object_url=None, object_text=None):
     """Handles objects included in the page."""
     attrib = {}
     if object_text:
         attrib[html.alt] = object_text
     if object_page is not None:
         att = 'attachment:'  # moin 1.9 needed this for an attached file
         if object_page.startswith(att):
             object_page = '/' + object_page[len(att):]  # now we have a subitem
         target = Iri(scheme='wiki.local', path=object_page)
         attrib[xinclude.href] = target
         element = xinclude.include(attrib=attrib)
     else:
         attrib[xlink.href] = object_url
         element = moin_page.object(attrib)
     stack.top_append(element)
Пример #20
0
    def absolute_path(self, path, current_page_path):
        """
        Converts a relative iri path into an absolute one

        :param path: the relative path to be converted
        :type path: Iri.path
        :param current_page_path: the path of the page where the link is
        :type current_page_path: Iri.path
        :returns: the absolute equivalent of the relative path
        :rtype: Iri.path
        """
        quoted_path = path.quoted
        # starts from 1 because 0 is always / for the current page
        quoted_current_page_path = current_page_path[1:].quoted

        abs_path = AbsItemName(quoted_current_page_path, quoted_path)
        abs_path = Iri(abs_path).path
        return abs_path
Пример #21
0
 def __call__(self, rev, contenttype=None, arguments=None):
     item_name = rev.item.name
     attrib = {
         moin_page.type_:
         unicode(self.input_type),
         xlink.href:
         Iri(scheme='wiki',
             authority='',
             path='/' + item_name,
             query='do=get&rev={0}'.format(rev.revid)),
     }
     obj = moin_page.object_(
         attrib=attrib,
         children=[
             u'Your Browser does not support HTML5 audio/video element.',
         ])
     body = moin_page.body(children=(obj, ))
     return moin_page.page(children=(body, ))
Пример #22
0
 def handle_wikilocal_links(self, elem, input, page):
     if input.path:
         # this can be a relative path, make it absolute:
         path = input.path
         if page:
             path = self.absolute_path(path, page.path)
         item_name = unicode(path)
         if not flaskg.storage.has_item(item_name):
             # XXX these index accesses slow down the link converter quite a bit
             elem.set(moin_page.class_, 'moin-nonexistent')
     else:
         item_name = unicode(page.path[1:])
     endpoint, rev, query = self._get_do_rev(input.query)
     url = url_for_item(item_name, rev=rev, endpoint=endpoint)
     if not page:
         url = url[1:]
     link = Iri(url, query=query, fragment=input.fragment)
     elem.set(self._tag_xlink_href, link)
Пример #23
0
    def macro(self, content, arguments, page_url, alternative):
        if arguments:
            item_count = int(arguments[0])
        else:
            item_count = 1

        all_item_names = self.get_item_names()

        # Now select random item from the full list, and if it exists and
        # we can read it, save.
        random_item_names = []
        found = 0
        while found < item_count and all_item_names:
            # Take one random item from the list
            item_name = random.choice(all_item_names)
            all_item_names.remove(item_name)

            # Filter out items the user may not read.
            try:
                item = Item.create(item_name)
                random_item_names.append(item_name)
                found += 1
            except AccessDenied:
                pass

        if not random_item_names:
            return

        random_item_names.sort()

        result = moin_page.span()
        for name in random_item_names:
            link = unicode(Iri(scheme=u'wiki', authority=u'',
                               path=u'/' + name))
            result.append(
                moin_page.a(attrib={xlink.href: link}, children=[name]))
            result.append(", ")

        del result[-1]  # kill last comma
        return result
Пример #24
0
    def internal_representation(self, attributes=None):
        """
        Return the internal representation of a document using a DOM Tree
        """
        hash_name = HASH_ALGORITHM
        hash_hexdigest = self.rev.meta.get(hash_name)
        if hash_hexdigest:
            cid = cache_key(usage="internal_representation",
                            hash_name=hash_name,
                            hash_hexdigest=hash_hexdigest,
                            attrs=repr(attributes))
            doc = app.cache.get(cid)
        else:
            # likely a non-existing item
            doc = cid = None
        if doc is None:
            # We will see if we can perform the conversion:
            # FROM_mimetype --> DOM
            # if so we perform the transformation, otherwise we don't
            from moin.converter import default_registry as reg
            input_conv = reg.get(Type(self.contenttype), type_moin_document)
            if not input_conv:
                raise TypeError("We cannot handle the conversion from {0} to the DOM tree".format(self.contenttype))
            smiley_conv = reg.get(type_moin_document, type_moin_document, icon='smiley')

            # We can process the conversion
            links = Iri(scheme='wiki', authority='', path='/' + self.name)
            doc = input_conv(self.rev, self.contenttype, arguments=attributes)
            # XXX is the following assuming that the top element of the doc tree
            # is a moin_page.page element? if yes, this is the wrong place to do that
            # as not every doc will have that element (e.g. for images, we just get
            # moin_page.object, for a tar item, we get a moin_page.table):
            doc.set(moin_page.page_href, unicode(links))
            if self.contenttype.startswith((u'text/x.moin.wiki', u'text/x-mediawiki', u'text/x.moin.creole', )):
                doc = smiley_conv(doc)
            if cid:
                app.cache.set(cid, doc)
        return doc
Пример #25
0
    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(moin_page.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 == xinclude.include:
                # we have already recursed several levels and found a transclusion: "{{SomePage}}" or <<Include(...)>>
                # process the transclusion and add it to the DOM.  Subsequent recursions will traverse through
                # the transclusion's elements.
                href = elem.get(xinclude.href)
                xpointer = elem.get(xinclude.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:
                    # we are working on an <<Include(abc)>> macro, not a {{transclusion}}
                    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
                            # TODO: These do not include all parameters in moin 1.9 Include macro docs:
                            # <<Include(pagename, heading, level, from="regex", to="regex", sort=ascending|descending, items=n, skipitems=n, titlesonly, editlink)>>
                            # these are currently unsupported in moin 2.0: from, to, titlesonly, editlink
                            if name == 'pages':  # pages == pagename in moin 1.9
                                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

                included_elements = []
                if href:
                    # We have a single page to transclude or include
                    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:
                    # we have regex of pages to include:  <<Include(^qqq)>>
                    query = And([
                        Term(WIKINAME, app.cfg.interwikiname),
                        Regex(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)
                    if not pagelist:
                        msg = _(
                            'Error: no items found matching "<<Include({0})>>"'
                        ).format(xp_include_pages)
                        attrib = {html.class_: 'moin-error'}
                        strong = ET.Element(moin_page.strong, attrib, (msg, ))
                        included_elements.append(strong)

                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

                    if xp_include_heading is not None:
                        attrib = {xlink.href: p_href}
                        children = (xp_include_heading or page.name, )
                        elem_a = ET.Element(moin_page.a,
                                            attrib,
                                            children=children)
                        attrib = {
                            moin_page.outline_level: xp_include_level or '1'
                        }
                        elem_h = ET.Element(moin_page.h,
                                            attrib,
                                            children=(elem_a, ))
                        included_elements.append(elem_h)

                    page_doc = page.content.internal_representation(
                        attributes=Arguments(keyword=elem.attrib))
                    if isinstance(page.rev.data, file):
                        page.rev.data.close()

                    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(moin_page.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()
Пример #26
0
 def inline_url_repl(self, stack, url, url_target):
     url = Iri(url_target)
     attrib = {xlink.href: url}
     element = moin_page.a(attrib=attrib, children=[url_target])
     stack.top_append(element)
Пример #27
0
def allowed_uri_scheme(uri):
    parsed = Iri(uri)
    return not parsed.scheme or parsed.scheme in URI_SCHEMES
Пример #28
0
def test_wikilocal(conv, input_, page, output):
    elem = ET.Element(None)
    conv.handle_wikilocal_links(elem, Iri(input_), Iri(page))
    assert elem.get(xlink.href) == output
Пример #29
0
def test_wikiexternal(conv, input_, output):
    elem = ET.Element(None)
    conv.handle_external_links(elem, Iri(input_))
    href = elem.get(xlink.href)
    assert href == output
Пример #30
0
    def inline_link_repl(self,
                         stack,
                         link,
                         link_url=None,
                         link_item=None,
                         link_args=u'',
                         external_link_url=None,
                         alt_text=u''):
        """Handle all kinds of links."""
        link_text = ''
        link_args_list = []
        # Remove the first pipe/space, example of link_args : |arg1|arg2 or " arg1 arg2"
        parsed_args = self.parse_args(link_args[1:])
        query = None
        if parsed_args.keyword:
            query = url_encode(parsed_args.keyword,
                               charset=CHARSET,
                               encode_keys=True,
                               sort=True)
        # Take the last of positional parameters as link_text(caption)
        if parsed_args.positional:
            link_text = parsed_args.positional.pop()
        if link_item is not None:
            if '#' in link_item:
                path, fragment = link_item.rsplit('#', 1)
            else:
                path, fragment = link_item, None
            target = Iri(scheme='wiki.local',
                         path=path,
                         query=query,
                         fragment=fragment)
            text = link_item
        else:
            if link_url and len(link_url.split(':')) > 0 and link_url.split(
                    ':')[0] == 'File':
                object_item = ':'.join(link_url.split(':')[1:])
                args = parsed_args.keyword
                if object_item is not None:
                    if 'do' not in args:
                        # by default, we want the item's get url for transclusion of raw data:
                        args['do'] = 'get'
                    query = url_encode(args,
                                       charset=CHARSET,
                                       encode_keys=True,
                                       sort=True)
                    target = Iri(scheme='wiki.local',
                                 path=object_item,
                                 query=query,
                                 fragment=None)
                    text = object_item
                else:
                    target = Iri(scheme='wiki.local', path=link_url)
                    text = link_url

                if not link_text:
                    link_text = text
                attrib = {xlink.href: target}
                attrib[moin_page.alt] = link_text

                element = moin_page.object(attrib)
                stack.push(element)
                if link_text:
                    self.preprocessor.push()
                    self.parse_inline(link_text, stack, self.inlinedesc_re)
                    self.preprocessor.pop()
                else:
                    stack.top_append(text)
                stack.pop()
                return
            target = Iri(scheme='wiki.local', path=link_url)
            text = link_url
        if external_link_url:
            target = Iri(external_link_url)
            text = alt_text
        element = moin_page.a(attrib={xlink.href: target})
        stack.push(element)
        if link_text:
            self.preprocessor.push()
            self.parse_inline(link_text, stack, self.inlinedesc_re)
            self.preprocessor.pop()
        else:
            stack.top_append(text)
        stack.pop()