Exemplo n.º 1
0
 def _process_node(self, node):
     # Avoid literals etc
     if not isinstance(node.parent, nodes.paragraph):
         return
     in_str = node.rawsource
     processed = txt_dollars_to_math(in_str)
     if MATH_MARKER not in processed:
         return
     parts = processed.split(MATH_MARKER)
     new_nodes = []
     for i, part in enumerate(parts):
         with_nulls = escape2null(part)
         to_backslashes = unescape(with_nulls, restore_backslashes=True)
         if part == '':
             continue
         if i % 2:  # See sphinx.ext.mathbase
             if SPHINX_ge_18:
                 new_node = math()
                 new_node += nodes.Text(to_backslashes, to_backslashes)
             else:
                 new_node = math(latex=to_backslashes)
         else:
             new_node = nodes.Text(unescape(with_nulls), to_backslashes)
         new_node.parent = node.parent
         new_nodes.append(new_node)
     # Put new nodes into parent's list of children
     new_children = []
     for child in node.parent.children:
         if not child is node:
             new_children.append(child)
         else:
             new_children += new_nodes
     node.parent.children = new_children
Exemplo n.º 2
0
 def visit_Text(self, node):
     parent = node.parent
     while parent:
         if isinstance(parent, node_blacklist):
             if DEBUG and any(i == 'math'
                              for i, _ in split_dollars(node.rawsource)):
                 print("sphinx-math-dollar: Skipping",
                       node,
                       "(node_blacklist = %s)" % (node_blacklist, ),
                       file=sys.stderr)
             return
         parent = parent.parent
     data = split_dollars(node.rawsource)
     nodes = []
     has_math = False
     for typ, text in data:
         if typ == "math":
             has_math = True
             nodes.append(math(text, Text(text)))
         elif typ == "text":
             nodes.append(Text(text))
         else:
             raise ValueError("Unrecognized type from split_dollars %r" %
                              typ)
     if has_math:
         node.parent.replace(node, nodes)
Exemplo n.º 3
0
 def visit_Text(self, node):
     parent = node.parent
     while parent:
         if isinstance(parent, node_blacklist):
             if DEBUG and any(i == 'math' for i, _ in split_dollars(str(node).replace('\x00', '\\'))):
                 print("sphinx-math-dollar: Skipping", node, "(node_blacklist = %s)" % (node_blacklist,), file=sys.stderr)
             return
         parent = parent.parent
     # See https://github.com/sympy/sphinx-math-dollar/issues/22
     data = split_dollars(str(node).replace('\x00', '\\'))
     nodes = []
     has_math = False
     for typ, text in data:
         if typ == "math":
             has_math = True
             nodes.append(math(text, Text(text)))
         elif typ == "text":
             nodes.append(Text(text))
         elif typ == "display math":
             has_math = True
             new_node = math_block(text, Text(text))
             new_node.attributes.setdefault('nowrap', False)
             new_node.attributes.setdefault('number', None)
             nodes.append(new_node)
         else:
             raise ValueError("Unrecognized type from split_dollars %r" % typ)
     if has_math:
         node.parent.replace(node, nodes)
Exemplo n.º 4
0
def f_role(
        typ, rawtext, text, lineno, inliner,  # pylint: disable=unused-argument
        options=None, content=None):  # pylint: disable=unused-argument
    """
    Role for formants caps.
    """
    text = 'F_{}'.format(text)
    return [nodes.math(text, text)], []
 def render_math_inline(self, token: SyntaxTreeNode) -> None:
     content = token.content
     if token.markup == "$$":
         # available when dmath_double_inline is True
         node = nodes.math_block(content, content, nowrap=False, number=None)
     else:
         node = nodes.math(content, content)
     self.add_line_and_source_path(node, token)
     self.current_node.append(node)
Exemplo n.º 6
0
 def render_math(self, token):
     if token.content.startswith("$$"):
         content = token.content[2:-2]
         node = nodes.math_block(content, content, nowrap=False, number=None)
     else:
         content = token.content[1:-1]
         node = nodes.math(content, content)
     self.add_line_and_source_path(node, token)
     self.current_node.append(node)
Exemplo n.º 7
0
 def render_text_latex(self, output: NotebookNode, index: int):
     data = output["data"]["text/latex"]
     return [
         nodes.math(
             text=strip_latex_delimiters(data),
             nowrap=False,
             number=None,
             classes=["output", "text_latex"],
         )
     ]
Exemplo n.º 8
0
 def render_text_latex_inline(self, data: MimeData) -> list[nodes.Element]:
     """Render a notebook text/latex mime data output."""
     # TODO should we always assume this is math?
     return [
         nodes.math(
             text=strip_latex_delimiters(data.string),
             nowrap=False,
             number=None,
             classes=["output", "text_latex"],
         )
     ]
Exemplo n.º 9
0
 def render_text_latex(self, output: NotebookNode, index: int):
     data = output["data"]["text/latex"]
     self.env.get_domain("math").data["has_equations"][self.env.docname] = True
     return [
         nodes.math(
             text=strip_latex_delimiters(data),
             nowrap=False,
             number=None,
             classes=["output", "text_latex"],
         )
     ]
Exemplo n.º 10
0
def ipa_role(
        typ, rawtext, text, lineno, inliner,  # pylint: disable=unused-argument
        options=None, content=None):  # pylint: disable=unused-argument
    """
    Role for small caps.
    """
    if text.startswith('/') and text.endswith('/'):
        text = '/\u200A{}\u2006/'.format(text[1:-1])
    if r'^\prime' in rawtext:
        rawtext = rawtext[6:-1]
        parts = rawtext.split(r'^\prime')
        node = None
        for i, part in enumerate(parts):
            if part:
                if node:
                    node += nodes.inline(part, part, classes=['ipa'])
                else:
                    node = nodes.inline(part, part, classes=['ipa'])
            if i < len(parts) - 1:
                node += nodes.math(r'^\prime', r'^\prime')
        return [node], []

    text = r'\mathstrut\mbox{' + text + r'}'
    return [nodes.math(text, text, )], []
Exemplo n.º 11
0
 def visit_script(self, node):
     if node.attrib.get("type", "").split(";")[0] == "math/tex":
         node.attrib.pop("type")
         parent = self.parse_stack_r[-1]
         if parent.tag == "span":
             return nodes.math()
         elif parent.tag == "div":
             # sphinx mathjax crashes without these attributes present
             math = nodes.math_block()
             math["nowrap"] = None
             math["number"] = None
             return math
         else:
             self.document.reporter.warning(
                 "math/tex script with unknown parent: %s" % parent.tag)
     else:
         return IGNORE_ALL_CHILDREN
Exemplo n.º 12
0
    def make_node(self, cls, element):
        node = cls()
        having_block_node = cls in HAVING_BLOCK_NODE
        if element.text and element.text != "\n":
            text = self.unescape_char(element.text)
            if HTML_PLACEHOLDER_RE.search(text):
                html_text = self.unescape_char(text, rawHtml=True)
                if html_text.startswith("<!--math"):
                    g = re.match(r"<!--math(.*?)-->", html_text, re.DOTALL)
                    if g:
                        node += nodes.math(text=g.group(1).strip(),
                                           latex=g.group(1).strip())
                else:
                    node += nodes.raw(format='html', text=html_text)
            elif having_block_node:
                node += nodes.paragraph(text=text)
            else:
                node += nodes.Text(text)
        for child in element:
            subnode = self.visit(child)
            if having_block_node and isinstance(subnode, INLINE_NODES):
                all_nodes_is_in_paragraph = True
                if len(node) == 0:
                    node += nodes.paragraph()
                node[0] += subnode
            else:
                all_nodes_is_in_paragraph = False
                node += subnode

            if child.tail and child.tail != "\n":
                tail = self.unescape_char(child.tail)
                if HTML_PLACEHOLDER_RE.search(tail):
                    node += nodes.raw(format='html', text=tail)
                elif all_nodes_is_in_paragraph:
                    node[0] += nodes.Text(tail)
                elif having_block_node:
                    node += nodes.paragraph(text=tail)
                else:
                    node += nodes.Text(tail)

        return node
Exemplo n.º 13
0
 def visit_Text(self, node):
     parent = node.parent
     while parent:
         if isinstance(parent, node_blacklist):
             return
         parent = parent.parent
     rawtext = node.rawsource
     data = rawtext.split("@@")
     if len(data) == 1:
         return
     nodes = []
     for i in range(len(data)):
         text = data[i]
         if i % 2 == 0:
             nodes.append(Text(text))
         else:
             formula = eval(text, pygrim.__dict__)
             latex = formula.latex()
             #nodes.append(literal(text, text))
             nodes.append(math(latex, Text(latex)))
             #nodes.append(math_block(latex, Text(latex)))
     node.parent.replace(node, nodes)
Exemplo n.º 14
0
 def render_math_single(self, token):
     content = token.content
     node = nodes.math(content, content)
     self.add_line_and_source_path(node, token)
     self.current_node.append(node)
Exemplo n.º 15
0
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    set_classes(options)
    text = utils.unescape(text, True)  # raw text without inline role markup
    node = nodes.math(rawtext, text, **options)
    return [node], []
Exemplo n.º 16
0
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    set_classes(options)
    i = rawtext.find("`")
    text = rawtext.split("`")[1]
    node = nodes.math(rawtext, text, **options)
    return [node], []
Exemplo n.º 17
0
def my_math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    text = 'E = mc^2'
    return [nodes.math(text, text)], []
Exemplo n.º 18
0
def ext_math_role(role, raw, text, line, inliner, options = {}, content = []):
  text = replace_mathdefs(inliner.document, raw.split('`')[1])
  return [math(raw, text)], []
Exemplo n.º 19
0
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
    i = rawtext.find('`')
    text = rawtext.split('`')[1]
    node = nodes.math(rawtext, text)
    return [node], []
Exemplo n.º 20
0
    def run(self):
        self.assert_has_content()
        env = self.state.document.settings.env
        if not hasattr(env, 'poi_all'):
            env.poi_all = {}
        if len(self.arguments) == 0:
            return [nodes.container()]

        if 'title' in self.options:
            if 'id' in self.options:
                raise SphinxError(u'Point of interest options can\'t contain both "title" and "id"; one of them should be provided as an argument instead')
            name = self.arguments[0]
            title_text = self.options['title']
        else:
            name = self.options.get('id')
            if not name:
                choices = string.ascii_lowercase + string.digits
                while True:
                    name = ''.join(random.choice(choices) for i in range(6))
                    if name not in env.poi_all:
                        break
            title_text = self.arguments[0]

        node = nodes.container()
        title = nodes.container()

        if 'not_in_book' in self.options:
            # Ignore this point of interest in the output since it shall not be
            # included in the A+ course materials (e-book).
            return []

        if 'no_poi_box' not in self.options:
            container_class = 'poi-container'
            content_name = name + '-content'

            # add an extra div to force content to desired height
            hcontainer_opts = {
                u'style': 'height:' + self.options.get('height', '') + ';',
                u'class': container_class + ' poi-content row',
            }
        else:
            container_class = 'no-poi-box'
            content_name = name
            hcontainer_opts = {
                u'style': 'height:' + self.options.get('height', '') + ';',
                u'class': 'row',
            }

        if 'bgimg' in self.options:
            static_host = os.environ.get('STATIC_CONTENT_HOST', None)
            if not static_host:
                logger.warning('Environment variable STATIC_CONTENT_HOST must be set to be able to use point of interest background', location=node)
            else:
                docname = env.docname
                imgname = self.options['bgimg'].split('/')[-1]
                imgpath = ('/').join(docname.split('/')[0:-1]) + '/' + self.options['bgimg']
                urlstring = 'background-image:url(' + static_host + '/_images/' + imgname + ');'
                hcontainer_opts['style'] = hcontainer_opts['style'] + urlstring
                # Add background image to env and builder so that it will
                # be correctly copied to static _images build directory
                env.images[imgpath] = ({docname}, imgname)
                env.app.builder.images[imgpath] = imgname

        hcontainer = aplus_nodes.html(u'div', hcontainer_opts)
        collapsible = nodes.container()

        contentnodes = []
        colseparator = '::newcol'
        colcontent = ''
        colcontent_l = []
        colwidths = None
        prevl = 0
        l = 0
        if 'columns' in self.options:
            cols = list(map(int,self.options['columns'].split()))
            allcols = sum(cols)
            colwidths = [x / allcols for x in cols]

        for batch in self.content:
            l += 1
            if batch == colseparator:
                cn = len(contentnodes)
                cwidth = None
                if colwidths:
                    cwidth = floor(colwidths[cn] * 12)
                cnode = nodes.container(colcontent)
                hcontainer.append(cnode)
                contentnodes.append((self.content[prevl:l-1], self.content_offset + prevl, cnode, cwidth))

                colcontent = ''
                prevl = l
            else:
                colcontent_l.append(batch)
                colcontent += batch
                colcontent += '\n'

        # add last column
        cnode = nodes.container(colcontent)
        hcontainer.append(cnode)
        cwidth = None
        if colwidths:
            cwidth = floor(colwidths[-1] * 12)
        contentnodes.append((self.content[prevl:], self.content_offset + prevl, cnode, cwidth))

        nav = nodes.container()
        links = nodes.container()
        # poi_nav node is later replaced by reference nodes which
        # need to be within a TextElement-node
        text = nodes.inline()
        poinav = poi_nav()
        # Create a relative path to the _build/html/_static/poi.png file
        # from the built HTML file of the current RST document.
        dir_depth = len(os.path.dirname(env.doc2path(env.docname, None)).split(os.path.sep))
        icon = aplus_nodes.html('img', {
            'src': ('../' * dir_depth) + '_static/poi.png',
            'alt': 'Point of interest icon',
            'class': 'poi-icon',
        })
        hidelink = aplus_nodes.html(u'a', {
            u'href':u'#' + content_name,
            u'data-toggle':u'collapse'})
        hidelink.append(icon)

        if ":math:" in title_text:
            math_eq = title_text.split('`')[1]
            math_node = nodes.math()
            math_node['latex'] = math_eq
            hidelink.append(math_node)
            title.append(hidelink)
            nav.append(title)
        else:
            hidelink.append(nodes.Text(title_text))
            title.append(hidelink)
            nav.append(title)
        text.append(poinav)
        links.append(text)
        nav.append(links)

        if 'no_poi_box' not in self.options:
            node.append(nav)

        node.append(collapsible)
        collapsible.append(hcontainer)

        numcols = len(contentnodes)
        for cont, offset, cnode, cwidth in contentnodes:
            # Bootstrap uses 12 unit grid
            if not cwidth:
                cwidth = int(12 / numcols)
            cnode['classes'] = ['col-sm-' + str(cwidth)]
            self.state.nested_parse(cont, offset, cnode, hcontainer)

        # poinav id needs to be added so that we can identify the node later when processing
        poinav['ids'].append(name)

        self.options['name'] = name
        self.add_name(node)
        collapsible['ids'].append(content_name)
        collapsible['classes'].extend([container_class, 'collapse'])
        node['classes'].extend(['poi'])
        if 'class' in self.options:
            node['classes'].extend(self.options['class'])
        title['classes'].extend(['poi-title'])
        links['classes'].extend(['poi-links'])

        if not 'hidden' in self.options:
            collapsible['classes'].extend(['in'])
        nav['classes'].extend([container_class])

        # poi_info needs to be stored to env to be able to construct the
        # refuris later
        poi_info = {
            'docname': env.docname,
        }
        if 'previous' in self.options:
            poi_info['previous'] = self.options['previous']
        if 'next' in self.options:
            poi_info['next'] = self.options['next']

        env.poi_all[name] = poi_info
        return [node]