PDF export (via manually running latex)
This commit is contained in:
3
src/content/pdf-export.tex/contents.lr
Normal file
3
src/content/pdf-export.tex/contents.lr
Normal file
@@ -0,0 +1,3 @@
|
||||
_template: makepdf.tex
|
||||
---
|
||||
_model: none
|
||||
1
src/content/recipes
Symbolic link
1
src/content/recipes
Symbolic link
@@ -0,0 +1 @@
|
||||
../../data/development/
|
||||
Submodule src/packages/force-update updated: 2c50ec35c0...9240ae59c4
@@ -4,11 +4,23 @@ from lektor.databags import Databags
|
||||
from markupsafe import Markup
|
||||
from datetime import datetime
|
||||
import unicodedata
|
||||
import lektor_html_to_tex as tex
|
||||
|
||||
# -------
|
||||
# Sorting
|
||||
|
||||
|
||||
def sorted_images(obj, attr='record_label'):
|
||||
return sorted(obj.attachments.images, key=lambda x: getattr(x, attr))
|
||||
|
||||
|
||||
def title_image(self, attr='record_label', small=False):
|
||||
img = (sorted_images(self, attr) or [None])[0]
|
||||
if img and small:
|
||||
img = img.thumbnail(200, 150, mode='crop')
|
||||
return img
|
||||
|
||||
|
||||
def sortKeyInt(x):
|
||||
return int(x[0]) if x[0] else 0
|
||||
|
||||
@@ -40,17 +52,24 @@ def noUmlaut(text):
|
||||
|
||||
|
||||
def replaceFractions(txt):
|
||||
res = ''
|
||||
res = ' '
|
||||
for c in u'-–—':
|
||||
if c in txt:
|
||||
txt = txt.replace(c, ' – ')
|
||||
for x in txt.split():
|
||||
if x == '':
|
||||
continue
|
||||
try:
|
||||
i = ['1/2', '1/3', '2/3', '1/4', '3/4', '1/8'].index(x)
|
||||
res += [u'½', u'⅓', u'⅔', u'¼', u'¾', u'⅛'][i]
|
||||
except ValueError:
|
||||
if x in u'-–—':
|
||||
res += u' - '
|
||||
if x == '–':
|
||||
res += '–'
|
||||
elif res[-1:] == '–':
|
||||
res += x
|
||||
else:
|
||||
res += ' ' + x
|
||||
return res.lstrip()
|
||||
return res.lstrip(' ')
|
||||
|
||||
|
||||
def numFillWithText(num, fill=u'★', empty=u'☆', total=5):
|
||||
@@ -186,12 +205,12 @@ class HelperPlugin(Plugin):
|
||||
partA, partB = partA.split('.', 1)
|
||||
return self.translations[alt][partA][partB]
|
||||
|
||||
def ingredientsForRecipe(recipe, alt='en'):
|
||||
def ingredientsForRecipe(recipe, alt='en', mode='raw'):
|
||||
meaList = self.settings[alt]['measures']
|
||||
repFrac = self.settings[alt]['replFrac']
|
||||
|
||||
for line in recipe['ingredients']:
|
||||
line = line.strip()
|
||||
line = tex.raw_text_to_tex(line).strip()
|
||||
if not line:
|
||||
continue
|
||||
elif line.endswith(':'):
|
||||
@@ -210,6 +229,8 @@ class HelperPlugin(Plugin):
|
||||
# groups[undefinedKey].update(groups.pop('_undefined'))
|
||||
return groups.items()
|
||||
|
||||
self.env.jinja_env.filters['sorted_images'] = sorted_images
|
||||
self.env.jinja_env.filters['title_image'] = title_image
|
||||
self.env.jinja_env.filters['rating'] = numFillWithText
|
||||
self.env.jinja_env.filters['replaceFractions'] = replaceFractions
|
||||
self.env.jinja_env.filters['enumIngredients'] = ingredientsForRecipe
|
||||
|
||||
5
src/packages/html-to-tex/.gitignore
vendored
Normal file
5
src/packages/html-to-tex/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
dist
|
||||
build
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.egg-info
|
||||
62
src/packages/html-to-tex/html2latex.sed
Normal file
62
src/packages/html-to-tex/html2latex.sed
Normal file
@@ -0,0 +1,62 @@
|
||||
# character set translations for LaTex special chars
|
||||
s?>.?>?g
|
||||
s?<.?<?g
|
||||
s?\\?\\backslash ?g
|
||||
s?{?\\{?g
|
||||
s?}?\\}?g
|
||||
s?%?\\%?g
|
||||
s?\$?\\$?g
|
||||
s?&?\\&?g
|
||||
s?#?\\#?g
|
||||
s?_?\\_?g
|
||||
s?~?\\~?g
|
||||
s?\^?\\^?g
|
||||
s? ?~?g
|
||||
# Paragraph borders
|
||||
s?<p>?\\par ?g
|
||||
s?</p>??g
|
||||
# Headings
|
||||
s?<title>\([^<]*\)</title>?\\section*{\1}?g
|
||||
s?<hn>?\\part{?g
|
||||
s?</hn>?}?g
|
||||
s?<h1>?\\section*{?g
|
||||
s?</h[0-9]>?}?g
|
||||
s?<h2>?\\subsection*{?g
|
||||
s?<h3>?\\subsubsection*{?g
|
||||
s?<h4>?\\paragraph*{?g
|
||||
s?<h5>?\\paragraph*{?g
|
||||
s?<h6>?\\subparagraph*{?g
|
||||
# UL is itemize
|
||||
s?<ul>?\\begin{itemize}?g
|
||||
s?</ul>?\\end{itemize}?g
|
||||
s?<ol>?\\begin{enumerate}?g
|
||||
s?</ol>?\\end{enumerate}?g
|
||||
s?<li>?\\item ?g
|
||||
s?</li>??g
|
||||
# DL is description
|
||||
s?<dl>?\\begin{description}?g
|
||||
s?</dl>?\\end{description}?g
|
||||
# closing delimiter for DT is first < or end of line which ever comes first NO
|
||||
#s?<dt>\([^<]*\)<?\\item[\1]<?g
|
||||
#s?<dt>\([^<]*\)$?\\item[\1]?g
|
||||
#s?<dd>??g
|
||||
#s?<dt>?\\item[?g
|
||||
#s?<dd>?]?g
|
||||
s?<dt>\([^<]*\)</dt>?\\item[\1]?g
|
||||
s?<dd>??g
|
||||
s?</dd>??g
|
||||
# Italics
|
||||
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
|
||||
# Get rid of Anchors
|
||||
s?<a href="\(http[^"]*\)">\([^<]*\)</a>?\\external{\1}{\2}?g
|
||||
s?<a[^>]*>??g
|
||||
s?</a>??g
|
||||
# after href replace
|
||||
s?"?''?g
|
||||
46
src/packages/html-to-tex/lektor_html_to_tex.py
Normal file
46
src/packages/html-to-tex/lektor_html_to_tex.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from lektor.pluginsystem import Plugin # , get_plugin
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
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)
|
||||
ps.wait()
|
||||
return o.decode('utf-8')
|
||||
|
||||
|
||||
def html_to_tex(html):
|
||||
return sed_repl_content(f_sed_a, html)
|
||||
|
||||
|
||||
def raw_text_to_tex(text):
|
||||
text = text.replace('\\', '\\backslash ').replace(' ', '~')
|
||||
for c in '}{%$&#_~^':
|
||||
if c in text:
|
||||
text = text.replace(c, '\\' + c)
|
||||
return text
|
||||
# return sed_repl_content(f_sed_b, text)
|
||||
|
||||
|
||||
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
|
||||
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:
|
||||
f.write('\\def\\builddir{' + builder.destination_path + '}')
|
||||
|
||||
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
|
||||
12
src/packages/html-to-tex/setup.py
Executable file
12
src/packages/html-to-tex/setup.py
Executable file
@@ -0,0 +1,12 @@
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='lektor-html-to-tex',
|
||||
py_modules=['lektor_html-to-tex'],
|
||||
version='1.0',
|
||||
entry_points={
|
||||
'lektor.plugins': [
|
||||
'html-to-tex = lektor_html_to_tex:HtmlToTex',
|
||||
]
|
||||
}
|
||||
)
|
||||
@@ -2,8 +2,8 @@ CACHE MANIFEST
|
||||
# Date build: {{ DATE_NOW }}
|
||||
|
||||
{%- macro _print_(items) -%}
|
||||
{%- for item in items -%}
|
||||
{{ item|replace('../', '', 1) }}
|
||||
{%- for item in items if not item.endswith('tex') -%}
|
||||
{{ item }}
|
||||
{% endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
@@ -33,10 +33,10 @@ CACHE MANIFEST
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
|
||||
{% set img = x.attachments.images.order_by('record_label').first() -%}
|
||||
{#{% set img = x | title_image(small=True) -%}
|
||||
{%- if img -%}
|
||||
{{- _add_(cacheList, img.thumbnail(200, 150, 'crop')) -}}
|
||||
{%- endif -%}
|
||||
{{- _add_(cacheList, img) -}}
|
||||
{%- endif -%}#}
|
||||
|
||||
{%- if x.datamodel.has_own_children -%}
|
||||
{{- loop(x.children) -}}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="tile-grid">
|
||||
{%- for recipe in recipes -%}
|
||||
{%- if limit == 0 or loop.index <= limit -%}
|
||||
{%- set img = recipe.attachments.images.order_by('record_label').first() -%}
|
||||
{%- set img = recipe | title_image(small=True) -%}
|
||||
<a href="{{ recipe|url }}">{#--#}
|
||||
<div class="recipe-tile">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
{#- show image or placeholder text #}
|
||||
{% if img -%}
|
||||
<img class="lozad" data-src="{{ img.thumbnail(200, 150, 'crop')|url }}">
|
||||
<img class="lozad" data-src="{{ img|url }}">
|
||||
{%- else -%}
|
||||
<div class="placeholder">No Image</div>
|
||||
{%- endif -%}
|
||||
|
||||
31
src/templates/makepdf.tex
Normal file
31
src/templates/makepdf.tex
Normal file
@@ -0,0 +1,31 @@
|
||||
{%- 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 %}
|
||||
@@ -4,7 +4,7 @@
|
||||
<article class="recipe">
|
||||
<!-- date added: {{ this.date }} -->
|
||||
<section id="img-carousel" class="v-scroll center">
|
||||
{%- for img in this.attachments.images.order_by('record_label') %}
|
||||
{%- for img in this | sorted_images %}
|
||||
<img class="lozad" data-src="{{ img|url }}" height="400">
|
||||
{%- endfor %}
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user