1
|
|
|
""" |
2
|
|
|
byceps.blueprints.snippet.templating |
3
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
:Copyright: 2006-2019 Jochen Kupperschmidt |
6
|
|
|
:License: Modified BSD, see LICENSE for details. |
7
|
|
|
""" |
8
|
|
|
|
9
|
|
|
import sys |
10
|
|
|
import traceback |
11
|
|
|
|
12
|
|
|
from flask import abort, g, render_template, url_for |
13
|
|
|
from jinja2 import TemplateNotFound |
14
|
|
|
|
15
|
|
|
from ...services.snippet import service as snippet_service |
16
|
|
|
from ...services.snippet.service import SnippetNotFound |
17
|
|
|
from ...services.snippet.transfer.models import Scope |
18
|
|
|
from ...util.templating import get_variable_value, load_template |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
def render_snippet_as_page(version): |
22
|
|
|
"""Render the given version of the snippet, or an error page if |
23
|
|
|
that fails. |
24
|
|
|
""" |
25
|
|
|
try: |
26
|
|
|
context = get_snippet_context(version) |
27
|
|
|
return render_template('snippet/view.html', **context) |
28
|
|
|
except TemplateNotFound: |
29
|
|
|
abort(404) |
30
|
|
|
except Exception as e: |
31
|
|
|
print('Error in snippet markup:', e, file=sys.stderr) |
32
|
|
|
traceback.print_exc() |
33
|
|
|
context = { |
34
|
|
|
'message': str(e), |
35
|
|
|
} |
36
|
|
|
return render_template('snippet/error.html', **context), 500 |
37
|
|
|
|
38
|
|
|
|
39
|
|
|
def get_snippet_context(version): |
40
|
|
|
"""Return the snippet context to insert into the outer template.""" |
41
|
|
|
template = _load_template_with_globals(version.body) |
42
|
|
|
|
43
|
|
|
current_page = get_variable_value(template, 'current_page') |
44
|
|
|
title = version.title |
45
|
|
|
head = _render_template(version.head) if version.head else None |
46
|
|
|
body = template.render() |
47
|
|
|
|
48
|
|
|
return { |
49
|
|
|
'title': title, |
50
|
|
|
'current_page': current_page, |
51
|
|
|
'head': head, |
52
|
|
|
'body': body, |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
def render_snippet_as_partial( |
57
|
|
|
name, *, scope=None, ignore_if_unknown=False, context=None |
58
|
|
|
): |
59
|
|
|
"""Render the latest version of the snippet with the given name and |
60
|
|
|
return the result. |
61
|
|
|
""" |
62
|
|
|
if scope is None: |
63
|
|
|
scope = Scope.for_site(g.site_id) |
64
|
|
|
|
65
|
|
|
current_version = snippet_service.find_current_version_of_snippet_with_name( |
66
|
|
|
scope, name |
67
|
|
|
) |
68
|
|
|
|
69
|
|
|
if current_version is None: |
70
|
|
|
if ignore_if_unknown: |
71
|
|
|
return '' |
72
|
|
|
else: |
73
|
|
|
raise SnippetNotFound(scope, name) |
74
|
|
|
|
75
|
|
|
if context is None: |
76
|
|
|
context = {} |
77
|
|
|
|
78
|
|
|
return _render_template(current_version.body, context=context) |
79
|
|
|
|
80
|
|
|
|
81
|
|
|
def _render_template(source, *, context=None): |
82
|
|
|
template = _load_template_with_globals(source) |
83
|
|
|
|
84
|
|
|
if context is None: |
85
|
|
|
context = {} |
86
|
|
|
|
87
|
|
|
return template.render(**context) |
88
|
|
|
|
89
|
|
|
|
90
|
|
|
def _load_template_with_globals(source): |
91
|
|
|
template_globals = { |
92
|
|
|
'render_snippet': render_snippet_as_partial, |
93
|
|
|
'url_for': url_for, |
94
|
|
|
'url_for_snippet': url_for_snippet, |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return load_template(source, template_globals=template_globals) |
98
|
|
|
|
99
|
|
|
|
100
|
|
|
def url_for_snippet(name): |
101
|
|
|
"""Render an URL pointing to the snippet document's mountpoint.""" |
102
|
|
|
return url_for(f'snippet.{name}') |
103
|
|
|
|