PDF export (fully automated with make target)

Generate tex files directly with python, not relying on lektor
This commit is contained in:
relikd
2020-11-16 15:27:21 +01:00
parent 07bb189da3
commit 39dc3a3575
10 changed files with 234 additions and 124 deletions

View File

@@ -1,3 +0,0 @@
_template: makepdf.tex
---
_model: none

View File

@@ -210,7 +210,9 @@ class HelperPlugin(Plugin):
repFrac = self.settings[alt]['replFrac']
for line in recipe['ingredients']:
line = tex.raw_text_to_tex(line).strip()
line = line.strip()
if mode == 'tex':
line = tex.raw_text_to_tex(line)
if not line:
continue
elif line.endswith(':'):

View File

@@ -50,13 +50,12 @@ s?<it>\([^<]*\)</it>?{\\it \1}?g
s?<em>\([^<]*\)</em>?{\\it \1}?g
s?<b>\([^<]*\)</b>?{\\bf \1}?g
s?<strong>\([^<]*\)</strong>?{\\bf \1}?g
# old unused, because lektor generated internally other urls then output
# s?<a href="\.\.[^"]*/\([^"/][^"/]*\)/*">[^<]*</a>?\\recipelink{\1}?g
# recipe specific
s?<a href="recipes/\([^"/]*\)/*">\([^<]*\)</a>?\\recipelink{\1}{\2}?g
s?<a href="../\([^"/]*\)/*">\([^<]*\)</a>?\\recipelink{\1}{\2}?g
# Get rid of Anchors
s?<a href="\(http[^"]*\)">\([^<]*\)</a>?\\external{\1}{\2}?g
s?<a[^>]*>??g
s?</a>??g
# after href replace
# quotes (replace after href)
s?\([[:space:]]\)"\([^[:space:]]\)?\1``\2?g
s?"?''?g

View File

@@ -1,21 +1,25 @@
# -*- coding: utf-8 -*-
from lektor.pluginsystem import Plugin # , get_plugin
import mistune
import os
import subprocess
import time
import subprocess as shell
import lektor_helper as helper
import lektor_time_duration as timedur
my_dir = os.path.dirname(os.path.realpath(__file__))
f_sed_a = os.path.join(my_dir, 'html2latex.sed')
def sed_repl_content(f_sed, content):
with subprocess.Popen(('echo', content), stdout=subprocess.PIPE) as ps:
o = subprocess.check_output(['sed', '-f', f_sed], stdin=ps.stdout)
def sed_repl_tex(f_sed, content):
with shell.Popen(('echo', content), stdout=shell.PIPE) as ps:
o = shell.check_output(['sed', '-f', f_sed], stdin=ps.stdout)
ps.wait()
return o.decode('utf-8')
def html_to_tex(html):
return sed_repl_content(f_sed_a, html)
return sed_repl_tex(f_sed_a, html)
def raw_text_to_tex(text):
@@ -24,23 +28,104 @@ def raw_text_to_tex(text):
if c in text:
text = text.replace(c, '\\' + c)
return text
# return sed_repl_content(f_sed_b, text)
# return sed_repl_tex(f_sed_b, text)
class RecipeToTex(object):
def __init__(self, enumerator):
super(RecipeToTex, self).__init__()
bases = tuple([]) + (mistune.Renderer,)
renderer_cls = type('renderer_cls', bases, {})
renderer = renderer_cls(escape=False)
self.mdparser = mistune.Markdown(renderer, escape=False)
self.enumerator = enumerator
def make(self, recipe, alt):
ingredients = ''
for x in self.enumerator(recipe, alt, mode='tex'):
ingredients += '\n' + self.process_ingredient(x, alt)
ingredients = ingredients[1:] or '\\item '
self.mdparser.renderer.record = recipe
instructions_html = self.mdparser(recipe['directions'].source)
instructions = sed_repl_tex(f_sed_a, instructions_html)
return self.process_recipe(recipe, alt, ingredients, instructions)
pass
def process_recipe(self, recipe, alt, ingredients, instructions):
img = helper.title_image(recipe)
if img:
img = img.path[:-4] + '@200x150_crop' + img.path[-4:]
duration = recipe['time']
host = recipe['source'].host
time = timedur.to_duration(duration, alt) if duration else ''
srcUrl = raw_text_to_tex(str(recipe['source'])) or ''
srcHost = raw_text_to_tex(host) if host else ''
return f'''
\\newrecipe{{{recipe['_slug']}}}{{{raw_text_to_tex(recipe['name'])}}}
\\meta{{{time}}}{{{recipe['yield'] or ''}}}
\\footer{{{srcUrl}}}{{{srcHost}}}
\\begin{{ingredients}}{{{img or ''}}}
{ingredients}
\\end{{ingredients}}
{instructions}
'''
def process_ingredient(self, ing, alt):
grp = ing.get('group')
if grp:
return f'\\ingGroup{{{grp}}}'
ret = ''
val = ing['value']
meas = ing['measure']
note = ing['note']
ret += '\\item'
if val or meas:
sep = '~' if val and meas else ''
ret += '[{}{}{}]'.format(val or '', sep, meas or '')
ret += f' \\ingName{{{ ing["name"] }}}' # keep space in front
if note:
ret += '\\ingDetail{'
for prt in note.split():
if prt.startswith('@../'):
ret += f' \\pagelink{{{ prt[4:].rstrip("/") }}}'
else:
ret += ' ' + prt
ret += '}'
return ret
class HtmlToTex(Plugin):
name = u'HTML to TEX converter'
description = u'Will convert html formatted text to (la)tex format.'
def on_before_build_all(self, builder, **extra):
# export current build dir
dest_file = my_dir
def on_after_prune(self, builder, **extra):
maketex = bool(builder.extra_flags.get('ENABLE_PDF_EXPORT'))
print('PDF Export: ' + ('ENABLED' if maketex else 'DISABLED'))
if not maketex:
return
dest_dir = my_dir
for x in range(3):
dest_file = os.path.dirname(dest_file)
dest_file = os.path.join(dest_file, 'extras', 'pdf-export',
'setup-builddir.tex')
with open(dest_file, 'w') as f:
dest_dir = os.path.dirname(dest_dir)
dest_dir = os.path.join(dest_dir, 'extras', 'pdf-export')
start_time = time.time()
print('PDF Export: generate tex files')
with open(os.path.join(dest_dir, 'dyn-builddir.tex'), 'w') as f:
# Export current build dir (for image search)
f.write('\\def\\builddir{' + builder.destination_path + '}')
parser = RecipeToTex(self.env.jinja_env.filters['enumIngredients'])
for alt in self.env.load_config().list_alternatives():
tex = ''
for recipe in builder.pad.get('/recipes', alt=alt).children:
tex += parser.make(recipe, alt)
fname = os.path.join(dest_dir, f'dyn-recipes-{alt}.tex')
with open(fname, 'w') as f:
f.write(tex)
print('PDF Export: done in %.2f sec' % (time.time() - start_time))
def on_setup_env(self, **extra):
self.env.jinja_env.filters['html_to_tex'] = html_to_tex
self.env.jinja_env.filters['raw_text_to_tex'] = raw_text_to_tex

View File

@@ -1,31 +0,0 @@
{%- set recipe_label = localize(this.alt, 'ingredients.recipeLink') %}
{%- for recipe in site.get('/recipes', this.alt).children %}
\newrecipe{ {{- recipe._slug }}}{ {{- recipe.name | raw_text_to_tex }}}
\meta{ {{- recipe.time|duration(this.alt) if recipe.time else '' }}}{ {{- recipe.yield or '' }}}
\footer{ {{- recipe.source | string | raw_text_to_tex or '' }}}{ {{- recipe.source.host | raw_text_to_tex if recipe.source.host else '' }}}
{%- set img = recipe | title_image(small=True) %}
\begin{ingredients}{ {%- if img %}{{ img|url }}{% else %}{% endif %}}
{%- for ing in recipe|enumIngredients(this.alt, mode='tex') %}
{%- if ing['group'] %}
\ingGroup{ {{- ing['group'] | raw_text_to_tex }}}
{%- else %}
\item
{%- if ing['value'] or ing['measure'] -%}
[{%- if ing['value'] %}{{ ing['value'] }}{% endif -%}
{%- if ing['measure'] %}~{{ ing['measure'] }}{% endif -%}]
{%- endif %} \ingName{ {{- ing['name'] -}}}
{%- if ing['note'] %}\ingDetail{
{%- for prt in ing['note'].split() -%}
{%- if prt.startswith('@../') %} \pagelink{ {{- prt[4:-1] -}} }
{%- else %} {{ prt -}}
{%- endif -%}
{%- endfor -%}}
{%- endif -%}
{%- endif -%}
{%- endfor %}
\end{ingredients}
{{ recipe.directions.html | html_to_tex }}
{%- endfor %}