django-tex icon indicating copy to clipboard operation
django-tex copied to clipboard

Is this still active?

Open arcstur opened this issue 3 years ago • 4 comments

I'm thinkgin about using this library instead of making my own simple solution, and even contributing to it.

However, there are 3 open PRs, from April, June and July of this year, that didn't receive any comments from @weinbusch. Are you still maintaining it?

Thanks!

arcstur avatar Oct 21 '22 14:10 arcstur

@arcstur I'm also considering it as option.

Did you encounter any breaking issues or is it working as intended, and if you did use it, which version of Django did you use it with?

Edit: Okay, so I decided to do my own research and I can render some basic PDF files, import packages etc. I tested it with Django 4.1.

Minor thing to watch out for is when writing {#n or #n}, (example: \setbox0=\hbox{#1\unskip}\ifdim\wd0=0pt) inside your tex file as Jinja thinks you are writing a comment, it appears you can get around this by seperating the hash and bracket with a space, e.g. { #n or #n }.

blue-hexagon avatar Mar 24 '23 15:03 blue-hexagon

Hey, I ended up building my own simple solution using some code snippets from here. I prefer using the tectonic engine, and adding suport for it here would not happen, since PRs are not being reviewed.

I also didn't need all the functionality, so it was fine.

arcstur avatar Mar 24 '23 17:03 arcstur

@arcstur, is it possible that you share some of your code using tectonic with the django-tex package?

Many thanks!

ramibch avatar Jun 16 '23 18:06 ramibch

@ramiboutas Sure. First I put jinja2 in backend

{
        'NAME': 'jinja2',
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [os.path.join(BASE_DIR, 'myappthatusestex/templates')],
        'APP_DIRS': False,
        'OPTIONS':{
            'environment': 'compile_tex.environment.custom_environment',
        }
}

This is the environment at compile_tex/environment.py

from jinja2 import Environment
from django.template.defaultfilters import register
from .compiler import latex_escape

FILTERS = register.filters.copy()
FILTERS.update({'latex_escape': latex_escape})

def custom_environment(**options):
    options.update(
        {
            "autoescape": None,
        }
    )
    env = Environment(**options)
    env.filters = FILTERS
    return env

Then, on compile_tex/compiler.py I have the compilation code and here are some snippets. I removed the caching part to focus on the important part.

from django.template import loader

def render_tex_template(template_name, context):
    tex_template = loader.get_template(template_name, using="jinja2")
    tex_string = tex_template.render(context)
    # define tex_path how you would like
    with open(tex_path, "w") as f:
        f.write(tex_string)

    return tex_path


def compile_tex_template(
    template_name, context
):
    tex_path = render_tex_template(template_name, context)

    try:
        subprocess.run(
            ["tectonic", "-X", "compile", tex_path],
            capture_output=True,
            check=True,
        )
    except subprocess.CalledProcessError as e:
        print(e.stdout, e.stderr)
        raise e

    pdf_path = os.path.splitext(tex_path)[0] + ".pdf"
    return pdf_path

# Obtained from pylatex
LATEX_REPLACE = {
    "\\": r"\textbackslash{}",
    "\n": "\\newline%\n",
    "\xA0": "~",  # Non-breaking space
    "&": r"\&",
    "%": r"\%",
    "$": r"\$",
    "#": r"\#",
    "_": r"\_",
    "{": r"\{",
    "}": r"\}",
    "~": r"\textasciitilde{}",
    "^": r"\^{}",
    "-": r"{-}",
    "[": r"{[}",
    "]": r"{]}",
    "'": r"\textquotesingle{}",
    '"': r"\textquotedbl{}",
}


def latex_escape(s):
    if s:
        for old, new in LATEX_REPLACE.items():
            s = s.replace(old, new)
    return s

It's not the best code, but works fine.

Then, for returning the PDF, in the views I have some code like this

# get pdf_path from compiler
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=filename.pdf'
with open(pdf_path, 'rb') as f:
    response.write(f.read())
return response

arcstur avatar Sep 12 '23 16:09 arcstur