Beispiel #1
0
 def visit_rubric(self, node: Element) -> None:
     self.ensure_eol()
     if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')):
         self.body.append('.SH ' + self.deunicode(node.astext()).upper() + '\n')
         raise nodes.SkipNode
     else:
         self.body.append('.sp\n')
Beispiel #2
0
def apply_source_workaround(node: Element) -> None:
    # workaround: nodes.term have wrong rawsource if classifier is specified.
    # The behavior of docutils-0.11, 0.12 is:
    # * when ``term text : classifier1 : classifier2`` is specified,
    # * rawsource of term node will have: ``term text : classifier1 : classifier2``
    # * rawsource of classifier node will be None
    if isinstance(node, nodes.classifier) and not node.rawsource:
        logger.debug('[i18n] PATCH: %r to have source, line and rawsource: %s',
                     get_full_module_name(node), repr_domxml(node))
        definition_list_item = node.parent
        node.source = definition_list_item.source
        node.line = definition_list_item.line - 1
        node.rawsource = node.astext()  # set 'classifier1' (or 'classifier2')
    elif isinstance(node, nodes.classifier) and not node.source:
        # docutils-0.15 fills in rawsource attribute, but not in source.
        node.source = node.parent.source
    if isinstance(node, nodes.image) and node.source is None:
        logger.debug('[i18n] PATCH: %r to have source, line: %s',
                     get_full_module_name(node), repr_domxml(node))
        node.source, node.line = node.parent.source, node.parent.line
    if isinstance(node, nodes.title) and node.source is None:
        logger.debug('[i18n] PATCH: %r to have source: %s',
                     get_full_module_name(node), repr_domxml(node))
        node.source, node.line = node.parent.source, node.parent.line
    if isinstance(node, nodes.term):
        logger.debug('[i18n] PATCH: %r to have rawsource: %s',
                     get_full_module_name(node), repr_domxml(node))
        # strip classifier from rawsource of term
        for classifier in reversed(list(node.parent.findall(nodes.classifier))):
            node.rawsource = re.sub(r'\s*:\s*%s' % re.escape(classifier.astext()),
                                    '', node.rawsource)
    if isinstance(node, nodes.topic) and node.source is None:
        # docutils-0.18 does not fill the source attribute of topic
        logger.debug('[i18n] PATCH: %r to have source, line: %s',
                     get_full_module_name(node), repr_domxml(node))
        node.source, node.line = node.parent.source, node.parent.line

    # workaround: literal_block under bullet list (#4913)
    if isinstance(node, nodes.literal_block) and node.source is None:
        node.source = get_node_source(node)

    # workaround: recommonmark-0.2.0 doesn't set rawsource attribute
    if not node.rawsource:
        node.rawsource = node.astext()

    if node.source and node.rawsource:
        return

    # workaround: some docutils nodes doesn't have source, line.
    if (isinstance(node, (
            nodes.rubric,  # #1305 rubric directive
            nodes.line,  # #1477 line node
            nodes.image,  # #3093 image directive in substitution
            nodes.field_name,  # #3335 field list syntax
    ))):
        logger.debug('[i18n] PATCH: %r to have source and line: %s',
                     get_full_module_name(node), repr_domxml(node))
        node.source = get_node_source(node) or ''
        node.line = 0  # need fix docutils to get `node.line`
        return
Beispiel #3
0
        def error_collector(data):
            # Mutate the data since it was just generated
            data.type = data['type']
            data.level = data['level']
            data.message = Element.astext(data.children[0])
            data.full_message = Element.astext(data)

            # Save the error
            errors.append(data)
Beispiel #4
0
        def error_collector(data):
            # Mutate the data since it was just generated
            data.type = data['type']
            data.level = data['level']
            data.message = Element.astext(data.children[0])
            data.full_message = Element.astext(data)

            # Save the error
            errors.append(data)
Beispiel #5
0
    def error_collector(data):
        # Mutate the data since it was just generated
        # DEV: We will generate negative line numbers for RST prolog errors
        data.line = data.get('line')
        if isinstance(data.line, int):
            data.line -= rst_prolog_line_offset
        data.source = data['source']
        data.level = data['level']
        data.type = data['type']
        data.message = Element.astext(data.children[0])
        data.full_message = Element.astext(data)

        # Save the error
        errors.append(data)
    def error_collector(data):
        # Mutate the data since it was just generated
        # DEV: We will generate negative line numbers for RST prolog errors
        data.line = data.get('line')
        if isinstance(data.line, int):
            data.line -= rst_prolog_line_offset
        data.source = data['source']
        data.level = data['level']
        data.type = data['type']
        data.message = Element.astext(data.children[0])
        data.full_message = Element.astext(data)

        # Save the error
        errors.append(data)
Beispiel #7
0
def add_reference(app: Sphinx, env: BuildEnvironment, node: Element,
                  contnode: TextElement) -> Optional[nodes.reference]:
    # Fix references in docstrings that are inherited from the base pytket.backends.Backend class.
    mapping = app.config.external_url_mapping
    if node.astext() in mapping:
        newnode = nodes.reference(
            "",
            "",
            internal=False,
            refuri=mapping[node.astext()],
            reftitle=node.get("reftitle", node.astext()),
        )
        newnode.append(contnode)
        return newnode
    return None
Beispiel #8
0
 def visit_reference(self, node: Element) -> None:
     title = chm_htmlescape(node.astext(), True)
     self.append('<OBJECT type="text/sitemap">')
     self.append('  <PARAM name="Name" value="%s" />' % title)
     self.append('  <PARAM name="Local" value="%s" />' % node['refuri'])
     self.append('</OBJECT>')
     raise nodes.SkipNode
Beispiel #9
0
    def visit_literal(self, node: Element) -> None:
        if 'kbd' in node['classes']:
            self.body.append(
                self.starttag(node,
                              'kbd',
                              '',
                              CLASS='docutils literal notranslate'))
            return
        lang = node.get("language", None)
        if 'code' not in node['classes'] or not lang:
            self.body.append(
                self.starttag(node,
                              'code',
                              '',
                              CLASS='docutils literal notranslate'))
            self.protect_literal_text += 1
            return

        opts = self.config.highlight_options.get(lang, {})
        highlighted = self.highlighter.highlight_block(node.astext(),
                                                       lang,
                                                       opts=opts,
                                                       location=node,
                                                       nowrap=True)
        starttag = self.starttag(
            node,
            "code",
            suffix="",
            CLASS="docutils literal highlight highlight-%s" % lang,
        )
        self.body.append(starttag + highlighted.strip() + "</code>")
        raise nodes.SkipNode
Beispiel #10
0
    def visit_literal_block(self, node: Element) -> None:
        if node.rawsource != node.astext():
            # most probably a parsed-literal block -- don't highlight
            return super().visit_literal_block(node)

        lang = node.get('language', 'default')
        linenos = node.get('linenos', False)
        highlight_args = node.get('highlight_args', {})
        highlight_args['force'] = node.get('force', False)
        opts = self.config.highlight_options.get(lang, {})

        if linenos and self.config.html_codeblock_linenos_style:
            linenos = self.config.html_codeblock_linenos_style

        highlighted = self.highlighter.highlight_block(node.rawsource,
                                                       lang,
                                                       opts=opts,
                                                       linenos=linenos,
                                                       location=node,
                                                       **highlight_args)
        starttag = self.starttag(node,
                                 'div',
                                 suffix='',
                                 CLASS='highlight-%s notranslate' % lang)
        self.body.append(starttag + highlighted + '</div>\n')
        raise nodes.SkipNode
Beispiel #11
0
 def visit_desc_parameter(self, node: nodes.Element) -> None:
     if not self.first_param:
         self.add_text(", ")
     else:
         self.first_param = 0
     self.add_text(node.astext())
     raise nodes.SkipNode
Beispiel #12
0
 def visit_reference(self, node: Element) -> None:
     title = chm_htmlescape(node.astext(), True)
     self.append('<OBJECT type="text/sitemap">')
     self.append('  <PARAM name="Name" value="%s" />' % title)
     self.append('  <PARAM name="Local" value="%s" />' % node['refuri'])
     self.append('</OBJECT>')
     raise nodes.SkipNode
Beispiel #13
0
    def visit_literal_block(self, node: Element) -> None:
        if node.rawsource != node.astext():
            # most probably a parsed-literal block -- don't highlight
            return super().visit_literal_block(node)

        lang = node.get('language', 'default')
        linenos = node.get('linenos', False)
        highlight_args = node.get('highlight_args', {})
        highlight_args['force'] = node.get('force', False)
        if lang is self.builder.config.highlight_language:
            # only pass highlighter options for original language
            opts = self.builder.config.highlight_options
        else:
            opts = {}

        highlighted = self.highlighter.highlight_block(
            node.rawsource,
            lang,
            opts=opts,
            linenos=linenos,
            location=(self.builder.current_docname, node.line),
            **highlight_args)
        starttag = self.starttag(node,
                                 'div',
                                 suffix='',
                                 CLASS='highlight-%s notranslate' % lang)
        self.body.append(starttag + highlighted + '</div>\n')
        raise nodes.SkipNode
Beispiel #14
0
    def dispatch_visit(self, node: nodes.Element) -> None:

        if self.stop:
            raise nodes.StopTraversal

        # Skip comments
        if isinstance(node, nodes.Invisible):
            raise nodes.SkipNode

        # Skip all admonitions
        if isinstance(node, nodes.Admonition):
            raise nodes.SkipNode

        # Mark start of nested lists
        if isinstance(node, nodes.Sequential):
            self.list_level += 1
            if self.list_level > 1:
                self.description += "-"

        # Skip the first title if it's the title of the page
        if not self.first_title_found and isinstance(node, nodes.title):
            self.first_title_found = True
            if node.astext() in self.known_titles:
                raise nodes.SkipNode

        if isinstance(node, nodes.raw) or isinstance(node.parent, nodes.literal_block):
            raise nodes.SkipNode

        # Only include leaf nodes in the description
        if len(node.children) == 0:
            text = node.astext().replace("\r", "").replace("\n", " ").strip()

            # Remove double spaces
            while text.find("  ") != -1:
                text = text.replace("  ", " ")

            # Put a space between elements if one does not already exist.
            if (
                len(self.description) > 0
                and len(text) > 0
                and self.description[-1] not in string.whitespace
                and text[0] not in string.whitespace + string.punctuation
            ):
                self.description += " "

            self.description += text
Beispiel #15
0
 def pass_to_format_logger(self, msg):
     if msg['type'] == 'ERROR':
         log = self.doc_logger.error
     elif msg['type'] == 'WARNING':
         log = self.doc_logger.warning
     else:
         return
     log(Element.astext(msg), line=msg['line'])
Beispiel #16
0
def clean_astext(node: Element) -> str:
    """Like node.astext(), but ignore images."""
    node = node.deepcopy()
    for img in node.traverse(nodes.image):
        img['alt'] = ''
    for raw in node.traverse(nodes.raw):
        raw.parent.remove(raw)
    return node.astext()
Beispiel #17
0
    def depart_paragraph(self, node: Element) -> None:
        within_admonition = isinstance(node.parent, nodes.Admonition)

        # Avoid wrapping paragraphs which are just URLs, such as those within
        # footnotes.
        looks_like_url = bool(re.match(r'(?i)^https?://[^ ]+?$', node.astext().strip()))

        if not within_admonition:
            self.end_state(wrap = not looks_like_url)
Beispiel #18
0
 def visit_title(self, node: Element) -> None:
     if isinstance(node.parent, addnodes.seealso):
         self.body.append('.IP "')
         return
     elif isinstance(node.parent, nodes.section):
         if self.section_level == 0:
             # skip the document title
             raise nodes.SkipNode
         elif self.section_level == 1:
             self.body.append('.SH %s\n' %
                              self.deunicode(node.astext().upper()))
             raise nodes.SkipNode
     return super().visit_title(node)
Beispiel #19
0
    def depart_title(self, node: Element) -> None:
        """Change the permalinks for headlines.

        - for headlines: "Copy link to section: <section title>"
        - for tables: "Copy link to this table"
        - for admonitions: "Copy link to this <type>"

        Admonitions don't have an ID by default.
        The AdmonitionID post-transform adds
        IDs to admonitions.
        """
        close_tag = self.context[-1]
        if (self.config.html_permalinks and self.builder.add_permalinks
                and node.parent.hasattr("ids") and node.parent["ids"]):
            # add permalink anchor to normal headings
            if close_tag.startswith("</h"):
                self.add_permalink_ref(
                    node.parent, _(f"Copy link to section: {node.astext()}."))
            # and to headings when the 'contents' directive is used
            elif close_tag.startswith("</a></h"):
                self.body.append("</a><a role='button' "
                                 "class='headerlink tooltipped tooltipped-ne' "
                                 'href="#{}" '
                                 'aria-label="Copy link to this section: {}">'.
                                 format(node.parent["ids"][0], node.astext()) +
                                 ICONS["headerlink"])
            elif isinstance(node.parent, nodes.table):
                self.body.append("</span>")
                self.add_permalink_ref(node.parent,
                                       _("Copy link to this table."))
            elif isinstance(node.parent, nodes.Admonition):
                admon_type = type(node.parent).__name__
                self.add_permalink_ref(node.parent,
                                       _(f"Copy link to this {admon_type}."))
        elif isinstance(node.parent, nodes.table):
            self.body.append("</span>")

        self.body.append(self.context.pop())
        if self.in_document_title:  # type: ignore
            self.title = self.body[self.in_document_title:-1]  # type: ignore
            self.in_document_title = 0
            self.body_pre_docinfo.extend(self.body)
            self.html_title.extend(self.body)
            del self.body[:]
Beispiel #20
0
    def visit_reference(self, node: Element) -> None:
        self.body.append(self.defs['reference'][0])
        # avoid repeating escaping code... fine since
        # visit_Text calls astext() and only works on that afterwards
        self.visit_Text(node)  # type: ignore
        self.body.append(self.defs['reference'][1])

        uri = node.get('refuri', '')
        if uri.startswith('mailto:') or uri.startswith('http:') or \
           uri.startswith('https:') or uri.startswith('ftp:'):
            # if configured, put the URL after the link
            if self.config.man_show_urls and node.astext() != uri:
                if uri.startswith('mailto:'):
                    uri = uri[7:]
                self.body.extend([
                    ' <',
                    self.defs['strong'][0], uri, self.defs['strong'][1],
                    '>'])
        raise nodes.SkipNode
Beispiel #21
0
 def visit_Text(self, node: nodes.Element) -> None:
     self.add_text(node.astext())
Beispiel #22
0
 def visit_title(self, node: nodes.Element) -> None:
     if isinstance(node.parent, nodes.Admonition):
         self.add_text(node.astext() + ": ")
         raise nodes.SkipNode
     self.new_state(0)
Beispiel #23
0
 def visit_desc_content(self, node: Element) -> None:
     """Add panel class to definitions."""
     if self.config.html_collapsible_definitions and len(node.astext()) > 0:
         self.body.append(self.starttag(node, "dd", CLASS="panel"))
     else:
         self.body.append(self.starttag(node, "dd"))
Beispiel #24
0
    def visit_literal_block(self, node: Element) -> None:
        """Overwrite code blocks.

        All code blocks have a header with at least a copy button.
        For code blocks with syntax highlighting, the language is
        shown on the left side and an optional caption is included
        in the center.
        """
        if node.rawsource == node.astext():
            # node doens't have markup, highlight it!
            lang = node.get("language", "default")
            linenos = node.get("linenos", False)
            highlight_args = node.get("highlight_args", {})
            highlight_args["force"] = node.get("force", False)

            if lang is self.builder.config.highlight_language:
                # only pass highlighter options for original language
                opts = self.builder.config.highlight_options
            else:
                opts = {}

            if linenos and self.builder.config.html_codeblock_linenos_style:
                linenos = "inline"

            highlighted = self.highlighter.highlight_block(
                node.rawsource,
                lang,
                opts=opts,
                linenos=linenos,
                location=node,
                **highlight_args,
            )

            # Code blocks that don't have a caption are not wrapped inside a <container>
            # node so we add the header here. With captions, see: visit_caption
            if not (isinstance(node.parent, nodes.container)
                    and node.parent.get("literal_block")):

                self.body.append(self.starttag(node, "div", CLASS="highlight"))

                code_header = "<div class='code-header'>\n"
                code_lang = lang.replace("default",
                                         "python").replace("console", "shell")
                code_header += f"<span class='code-lang'>{code_lang}</span>\n"
                code_header += COPY_BUTTON
                code_header += "</div>\n"
                self.body.append(code_header)

            # wrap the highlighted string in a div
            self.body.append(highlighted)

            if not (isinstance(node.parent, nodes.container)
                    and node.parent.get("literal_block")):
                self.body.append("</div>\n")
            # we already included everything here in the `highlighted` string,
            # so we need to skip further processing
            raise nodes.SkipNode
        else:
            # node has markup, it's a samp directive or parsed-literal
            self.body.append(self.starttag(node, "div", CLASS="highlight"))
            code_header = "<div class='code-header'>\n"
            code_header += COPY_BUTTON
            code_header += "</div>\n"
            self.body.append(code_header)
            self.body.append("<pre><code>")
Beispiel #25
0
    def _resolve_numref_xref(self, env: "BuildEnvironment", fromdocname: str,
                             builder: "Builder", typ: str, target: str,
                             node: pending_xref, contnode: Element) -> Element:
        if target in self.labels:
            docname, labelid, figname = self.labels.get(target, ('', '', ''))
        else:
            docname, labelid = self.anonlabels.get(target, ('', ''))
            figname = None

        if not docname:
            return None

        target_node = env.get_doctree(docname).ids.get(labelid)
        figtype = self.get_enumerable_node_type(target_node)
        if figtype is None:
            return None

        if figtype != 'section' and env.config.numfig is False:
            logger.warning(__('numfig is disabled. :numref: is ignored.'),
                           location=node)
            return contnode

        try:
            fignumber = self.get_fignumber(env, builder, figtype, docname,
                                           target_node)
            if fignumber is None:
                return contnode
        except ValueError:
            logger.warning(__("no number is assigned for %s: %s"),
                           figtype,
                           labelid,
                           location=node)
            return contnode

        try:
            if node['refexplicit']:
                title = contnode.astext()
            else:
                title = env.config.numfig_format.get(figtype, '')

            if figname is None and '{name}' in title:
                logger.warning(__('the link has no caption: %s'),
                               title,
                               location=node)
                return contnode
            else:
                fignum = '.'.join(map(str, fignumber))
                if '{name}' in title or 'number' in title:
                    # new style format (cf. "Fig.{number}")
                    if figname:
                        newtitle = title.format(name=figname, number=fignum)
                    else:
                        newtitle = title.format(number=fignum)
                else:
                    # old style format (cf. "Fig.%s")
                    newtitle = title % fignum
        except KeyError as exc:
            logger.warning(__('invalid numfig_format: %s (%r)'),
                           title,
                           exc,
                           location=node)
            return contnode
        except TypeError:
            logger.warning(__('invalid numfig_format: %s'),
                           title,
                           location=node)
            return contnode

        return self.build_reference_node(fromdocname,
                                         builder,
                                         docname,
                                         labelid,
                                         newtitle,
                                         'numref',
                                         nodeclass=addnodes.number_reference,
                                         title=title)
Beispiel #26
0
 def visit_field(self, node: nodes.Element) -> None:
     print("Visit field", node.astext())
     pass
Beispiel #27
0
 def visit_raw(self, node: Element) -> None:
     if 'manpage' in node.get('format', '').split():
         self.body.append(node.astext())
     raise nodes.SkipNode
Beispiel #28
0
 def visit_citation_reference(self, node: nodes.Element) -> None:
     self.add_text("[%s]" % node.astext())
     raise nodes.SkipNode
Beispiel #29
0
 def visit_field_name(self, node: nodes.Element) -> None:
     print("Visit field name", node.astext())
     self.new_state(0)
Beispiel #30
0
 def visit_system_message(self, node: nodes.Element) -> None:
     self.new_state(0)
     self.add_text("<SYSTEM MESSAGE: %s>" % node.astext())
     self.end_state()
     raise nodes.SkipNode
Beispiel #31
0
 def visit_raw(self, node: nodes.Element) -> None:
     if "text" in node.get("format", "").split():
         self.new_state(0)
         self.add_text(node.astext())
         self.end_state(wrap=False)
     raise nodes.SkipNode
Beispiel #32
0
 def stringify(name: str, node: Element) -> str:
     reftitle = node.get('reftitle', node.astext())
     return ':%s:`%s`' % (name, reftitle)
Beispiel #33
0
 def visit_raw(self, node: Element) -> None:
     if 'text' in node.get('format', '').split():
         self.new_state(0)
         self.add_text(node.astext())
         self.end_state(wrap=False)
     raise nodes.SkipNode