Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use pylatex to render latex #78

Open
Freakwill opened this issue Jan 26, 2019 · 2 comments
Open

use pylatex to render latex #78

Freakwill opened this issue Jan 26, 2019 · 2 comments

Comments

@Freakwill
Copy link
Contributor

Freakwill commented Jan 26, 2019

Pylatex can produce more pretty latex codes.

class MyEnv(Environment):
    passenv = MyEnv(options='hehe',data=['blahblah', 'blahblah'])
env.dumps()

# '\\begin{myenv}[hehe]%\nblahblah%\nblahblah%\n\\end{myenv}'

c = Command('mycmd', arguments=['bling', 'bling'])
c.dumps()
# '\\mycmd{bling}{bling}'
@miyuchina
Copy link
Owner

I'm interested in this. Will you be willing to write a renderer for this, preferably in pylatex_renderer, so that people who do not want to install an additional package have the default latex_renderer to fallback on?

If not, I can also look into this in a few. Thanks for the suggestion!

@Freakwill
Copy link
Contributor Author

Freakwill commented Jun 10, 2019

Following is just an attempt, not applying all features of pylatex, such as package propagating, there must be a better one.

pylatex_renderer.py:

# -*- coding: utf-8 -*-

"""
LaTeX renderer for mistletoe with pylatex.
"""

import mistletoe.latex_token as latex_token
from mistletoe.base_renderer import BaseRenderer

from pylatex import *
from pylatex.base_classes import *
from pylatex.utils import *

class PyLaTeXRenderer(BaseRenderer):
    def __init__(self, *extras):
        """
        Args:
            extras (list): allows subclasses to add even more custom tokens.
        """
        tokens = self._tokens_from_module(latex_token)
        self.packages = []
        super().__init__(*tokens, *extras)

    def render_strong(self, token):
        return bold(self.render_inner(token))

    def render_emphasis(self, token):
        return Command('textit', arguments=self.render_inner(token))

    def render_inline_code(self, token):
        return verbatim(self.render_inner(token))

    def render_strikethrough(self, token):
        self.packages.append(Package('ulem', options='normalem'))
        return Command('sout', data=self.render_inner(token))

    def render_image(self, token):
        self.packages.append(Package('graphicx'))
        return StandAloneGraphic(token.src)

    def render_link(self, token):
        self.packages.append(Package('hyperref'))
        inner = self.render_inner(token)
        return Command('href', arguments=[token.target, inner])

    def render_auto_link(self, token):
        self.packages.append(Package('hyperref'))
        return Command('url', token.target)

    @staticmethod
    def render_math(token):
        return token.content

    def render_escape_sequence(self, token):
        return self.render_inner(token)

    def render_raw_text(self, token, escape=True):
        return escape_latex(token.content) if escape else token.content

    def render_heading(self, token):
        inner = self.render_inner(token)
        if token.level == 1:
            return Section(inner)
        elif token.level == 2:
            return Subsection(inner)
        return Subsubsection(inner)

    def render_quote(self, token):
        self.packages.append(Package('csquotes'))
        class displayquote(Environment):
            packages = ['csquotes']
            data=self.render_inner(token)
        return displayquote.dumps()

    def render_paragraph(self, token):
        return '\n{}\n'.format(self.render_inner(token))

    def render_block_code(self, token):
        self.packages.append(Package('listings'))
        class lstlisting(Environment):
            packages = ['listings']
            options = Options(f'language={token.language}')
            data=[self.render_raw_text(token.children[0], False)]
        return lstlisting.dumps()

    def render_list(self, token):
        self.packages.append(Package('listings'))
        tag = Enumerate if token.start is not None else Itemize
        return tag(data=self.render_inner(token))

    def render_list_item(self, token):
        return self.render_inner(token)

    def render_table(self, token):
        def render_align(column_align):
            if column_align != [None]:
                return ''.join(map(get_align, token.column_align))
            else:
                return ''

        def get_align(col):
            if col is None:
                return 'l'
            elif col == 0:
                return 'c'
            elif col == 1:
                return 'r'
            raise RuntimeError('Unrecognized align option: ' + col)

        if hasattr(token, 'header'):
            head_inner = self.render_table_row(token.header)
            tab.add_row(head_inner)
            tab.add_hline()
        inner = self.render_inner(token)
        align = render_align(token.column_align)
        tab = Tabular(align)
        tab.add_row(inner)
        return tab.dumps()

    def render_table_row(self, token):
        return dumps_list(token.children, token='&', mapper=self.render)

    def render_table_cell(self, token):
        return self.render_inner(token)

    @staticmethod
    def render_thematic_break(token):
        return Command('hrulefill').dumps()

    @staticmethod
    def render_line_break(token):
        return '\n' if token.soft else Command('newline').dumps()+'\n'

    def render_document(self, token):
        self.footnotes.update(token.footnotes)
        with Document(packages=self.packages) as doc:
            doc.data=self.render_inner(token)
            return doc.dumps()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants