136 lines
4.4 KiB
Python
136 lines
4.4 KiB
Python
from pyramid.view import (
|
|
view_config,
|
|
render_view_to_response,
|
|
)
|
|
from pyramid.renderers import render_to_response
|
|
from pyramid.httpexceptions import (HTTPFound, HTTPNotFound)
|
|
from pyramid.response import FileResponse
|
|
from pyramid.path import AssetResolver
|
|
from pathlib import PurePath
|
|
from ..resources import (Folder, Document, Markdown, YAML, Jinja2)
|
|
import yaml
|
|
import frontmatter
|
|
import markdown
|
|
|
|
from ..filters import IgnoreExtension
|
|
|
|
|
|
class Loader(yaml.Loader):
|
|
def __init__(self, stream):
|
|
super(Loader, self).__init__(stream)
|
|
Loader.add_constructor('!include', Loader.include)
|
|
Loader.add_constructor('!markdown', Loader.markdown)
|
|
|
|
def include(self, node):
|
|
if isinstance(node, yaml.ScalarNode):
|
|
return self.extractFile(self.construct_scalar(node))
|
|
|
|
elif isinstance(node, yaml.SequenceNode):
|
|
return [self.extractFile(filename)
|
|
for filename in self.construct_sequence(node)]
|
|
|
|
elif isinstance(node, yaml.MappingNode):
|
|
result = {}
|
|
for k, v in self.construct_mapping(node).items():
|
|
result[k] = self.extractFile(v)
|
|
return result
|
|
|
|
else:
|
|
raise yaml.constructor.ConstructorError(
|
|
"Error:: unrecognised node type in !include statement")
|
|
|
|
def markdown(self, node):
|
|
if not isinstance(node, yaml.ScalarNode):
|
|
raise yaml.constructor.ConstructorError(
|
|
"Error:: unrecognised node type in !markdown statement")
|
|
m = self.construct_scalar(node)
|
|
return markdown.markdown(
|
|
m,
|
|
extensions=[IgnoreExtension(), 'markdown.extensions.extra'],
|
|
output_format='html5',
|
|
tab_length=2)
|
|
|
|
def extractFile(self, filename):
|
|
path = PurePath(self.data_dir) / filename
|
|
f = AssetResolver().resolve(str(path)).stream()
|
|
if f:
|
|
if path.suffix in ['.yaml', '.yml', '.json']:
|
|
return yaml.load(f, Loader)
|
|
return f.read().decode()
|
|
|
|
|
|
def LoaderFactory(data_dir):
|
|
cl = Loader
|
|
cl.data_dir = data_dir
|
|
return cl
|
|
|
|
|
|
class CustomYAMLHandler(frontmatter.YAMLHandler):
|
|
def __init__(self, data_dir):
|
|
self.loader = LoaderFactory(data_dir)
|
|
|
|
def load(self, fm, **kwargs):
|
|
return yaml.load(fm, self.loader)
|
|
|
|
|
|
class PagesView:
|
|
def __init__(self, context, request):
|
|
self.context = context
|
|
self.request = request
|
|
|
|
@view_config(context=Folder)
|
|
def folder(self):
|
|
if 'index' not in self.context:
|
|
raise HTTPNotFound
|
|
return render_view_to_response(self.context['index'], self.request)
|
|
|
|
@view_config(context=Document)
|
|
def document(self):
|
|
return FileResponse(
|
|
AssetResolver().resolve(self.context.__path__).abspath(),
|
|
request=self.request)
|
|
|
|
def process_yaml(self):
|
|
if 'redirect' in self.post:
|
|
return HTTPFound(location=self.post.redirect)
|
|
if 'menu' not in self.post:
|
|
self.post['menu'] = yaml.load(
|
|
AssetResolver().resolve(
|
|
str(PurePath(self.request.registry.settings['data_dir']) /
|
|
'menu/default.yaml')).stream(),
|
|
LoaderFactory(self.request.registry.settings['data_dir']))
|
|
response = render_to_response(
|
|
'{0}.jinja2'.format(
|
|
self.post.get('template', 'default')),
|
|
self.post,
|
|
request=self.request
|
|
)
|
|
if 'content_type' in self.post:
|
|
response.content_type = self.post['content_type']
|
|
return response
|
|
|
|
@view_config(context=YAML)
|
|
def yaml(self):
|
|
self.post = yaml.load(
|
|
AssetResolver().resolve(
|
|
self.context.__path__).stream(),
|
|
LoaderFactory(self.request.registry.settings['data_dir']))
|
|
return self.process_yaml()
|
|
|
|
@view_config(context=Markdown)
|
|
def markdown(self):
|
|
self.post = frontmatter.load(
|
|
AssetResolver().resolve(
|
|
self.context.__path__).stream(),
|
|
handler=CustomYAMLHandler(self.request.registry.settings['data_dir']),
|
|
).to_dict()
|
|
return self.process_yaml()
|
|
|
|
@view_config(context=Jinja2)
|
|
def jinja2(self):
|
|
return render_to_response(
|
|
self.context.path,
|
|
{},
|
|
request=self.request
|
|
)
|