This repository has been archived on 2020-09-29. You can view files and clone it, but cannot push or open issues/pull-requests.
flatfilecms/flatfilecms/views/pages.py

121 lines
3.9 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
class Loader(yaml.Loader):
def __init__(self, stream):
super(Loader, self).__init__(stream)
Loader.add_constructor('!include', Loader.include)
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 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
)